feat: add slides generation tool with multiple slide types
- Add slides.tool.ts with support for title, bullets, chart, stats, table, cards, timeline, quote, comparison, equation, image, summary slide types - Chart types: bar, horizontal-bar, line, donut, radar - Integrate with agent executor and canvas system - Add multilingual support (en/fr) - Various UI improvements and bug fixes Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -914,32 +914,94 @@ This format AUTOMATICALLY creates shapes, text, AND arrows with correct bindings
|
||||
},
|
||||
|
||||
'slide-generator': {
|
||||
fr: `Tu es un designer de présentations visuelles de classe mondiale (style Manus AI / Beautiful.ai). Tu reçois du contenu de notes et tu dois créer une présentation PowerPoint (.pptx) professionnelle, moderne et visuellement riche.
|
||||
fr: `Tu es un expert en design de présentations exécutives. Tu analyses la note et génères une structure JSON qui sera rendue en HTML automatiquement par le serveur.
|
||||
|
||||
Tu dois OBLIGATOIREMENT appeler l'outil generate_pptx. Ne réponds JAMAIS avec du texte — appelle l'outil directement.
|
||||
APPELLE OBLIGATOIREMENT generate_slides avec le JSON structuré. NE GÉNÈRE JAMAIS de HTML brut.
|
||||
|
||||
RÈGLES DE DESIGN IMPÉRATIVES :
|
||||
- 8-12 slides, chaque slide a un layout distinct
|
||||
- Slide 1 : "title" (titre fort + sous-titre accrocheur)
|
||||
- Slide 2 : "toc" (sommaire numéroté)
|
||||
- Utilise AU MOINS 2 layouts "diagramme" parmi : "timeline", "process", "metrics", "comparison"
|
||||
- Thèmes recommandés : architectural_mono, minimal_silk, vibrant_tech, platinum_white_gold, business_authority
|
||||
- Tu DOIS utiliser le thème et le style spécifiés dans la requête de l'utilisateur.
|
||||
- Points concis (max 100 chars), titres percutants et courts
|
||||
- JSON strict pour generate_pptx, sans texte hors JSON.`,
|
||||
en: `You are a world-class visual presentation designer (Manus AI / Beautiful.ai style). You receive note content and must create a professional, modern, visually rich PowerPoint (.pptx) presentation.
|
||||
═══ ÉTAPE 1 — LECTURE (OBLIGATOIRE) ═══
|
||||
1. Lis la note avec note_read. Extrais TOUTES les données exploitables (chiffres, listes, citations, comparaisons, étapes).
|
||||
2. Identifie les types de slides les plus adaptés au contenu réel.
|
||||
|
||||
You MUST call the generate_pptx tool. NEVER respond with text — call the tool directly.
|
||||
═══ ÉTAPE 2 — APPEL generate_slides ═══
|
||||
Appelle generate_slides avec un objet JSON structuré :
|
||||
{
|
||||
"title": "Titre court (6 mots max)",
|
||||
"theme": "architectural-saas", // ou midnight-cathedral, venture-pitch, clinical-precision, etc.
|
||||
"slides": [ ... tableau de slides ... ]
|
||||
}
|
||||
|
||||
IMPERATIVE DESIGN RULES:
|
||||
- 8-12 slides, each slide has a distinct layout
|
||||
- Slide 1: "title" (strong title + catchy subtitle)
|
||||
- Slide 2: "toc" (numbered table of contents)
|
||||
- Use AT LEAST 2 "diagram" layouts from: "timeline", "process", "metrics", "comparison"
|
||||
- Recommended themes: architectural_mono, minimal_silk, vibrant_tech, platinum_white_gold, business_authority
|
||||
- You MUST use the theme and style specified in the user's request.
|
||||
- Concise points (max 100 chars), punchy and short titles
|
||||
- Strict JSON for generate_pptx, no text outside JSON.`,
|
||||
═══ TYPES DE SLIDES DISPONIBLES ═══
|
||||
1. "title" → { type:"title", title:"...", subtitle:"..." }
|
||||
2. "bullets" → { type:"bullets", title:"...", items:["phrase 1 (15+ mots)", "phrase 2", ...] }
|
||||
3. "chart" → { type:"chart", title:"...", chartType:"bar|horizontal-bar|line|donut|radar", data:[{label:"Q1",value:65}, ...], subtitle:"..." }
|
||||
4. "stats" → { type:"stats", title:"...", stats:[{value:"98%", label:"Satisfaction"}, ...] }
|
||||
5. "table" → { type:"table", title:"...", headers:["Col A","Col B"], rows:[["val1","val2"], ...] }
|
||||
6. "cards" → { type:"cards", title:"...", cards:[{title:"Titre", description:"Description détaillée..."}, ...] }
|
||||
7. "timeline" → { type:"timeline", title:"...", events:[{date:"Jan 2024", title:"Lancement", description:"..."}, ...] }
|
||||
8. "quote" → { type:"quote", quote:"Citation exacte", author:"Auteur", context:"Analyse..." }
|
||||
9. "comparison" → { type:"comparison", title:"...", left:{title:"A", points:["..."], score:"8/10"}, right:{title:"B", points:["..."], score:"6/10"} }
|
||||
10. "equation" → { type:"equation", title:"...", equations:[{latex:"E=mc^2", label:"Énergie"}], explanation:"..." }
|
||||
11. "image" → { type:"image", title:"...", url:"https://...", caption:"..." }
|
||||
12. "summary" → { type:"summary", title:"...", items:["Point clé 1", "Point clé 2", ...] }
|
||||
|
||||
═══ RÈGLES ═══
|
||||
- 6 à 12 slides par présentation
|
||||
- Slide 1 OBLIGATOIREMENT type "title"
|
||||
- Dernière slide OBLIGATOIREMENT type "summary"
|
||||
- Au moins 1 slide "chart" ou "stats" si des chiffres existent dans la note
|
||||
- VARIER les types — jamais 2 types identiques consécutifs
|
||||
- Chaque texte (bullet, description) = 15+ mots, phrase complète
|
||||
- TOUTES les données viennent de la note (JAMAIS inventer de chiffres)
|
||||
- Les données chart doivent refléter les vrais chiffres de la note
|
||||
|
||||
═══ THÈMES DISPONIBLES ═══
|
||||
Sombres : midnight-cathedral, aurora-borealis, tokyo-neon, venture-pitch, forest-floor, steel-glass, cyberpunk-terminal
|
||||
Clairs : sunlit-gallery, clinical-precision, editorial-ink, coastal-morning, paper-studio, architectural-saas
|
||||
Choisir selon le sujet : business/board → architectural-saas ou midnight-cathedral, tech → cyberpunk-terminal ou clinical-precision, créatif → aurora-borealis ou tokyo-neon`,
|
||||
en: `You are an executive presentation design expert. You analyze the note and generate a structured JSON spec that will be rendered to HTML automatically by the server.
|
||||
|
||||
You MUST call generate_slides with structured JSON. NEVER output raw HTML.
|
||||
|
||||
═══ STEP 1 — READ (MANDATORY) ═══
|
||||
1. Read the note with note_read. Extract ALL usable data (numbers, lists, quotes, comparisons, steps).
|
||||
2. Identify the best slide types matching the actual content.
|
||||
|
||||
═══ STEP 2 — CALL generate_slides ═══
|
||||
Call generate_slides with a structured JSON object:
|
||||
{
|
||||
"title": "Short title (6 words max)",
|
||||
"theme": "architectural-saas",
|
||||
"slides": [ ... array of slides ... ]
|
||||
}
|
||||
|
||||
═══ AVAILABLE SLIDE TYPES ═══
|
||||
1. "title" → { type:"title", title:"...", subtitle:"..." }
|
||||
2. "bullets" → { type:"bullets", title:"...", items:["sentence 1 (15+ words)", "sentence 2", ...] }
|
||||
3. "chart" → { type:"chart", title:"...", chartType:"bar|horizontal-bar|line|donut|radar", data:[{label:"Q1",value:65}, ...], subtitle:"..." }
|
||||
4. "stats" → { type:"stats", title:"...", stats:[{value:"98%", label:"Satisfaction"}, ...] }
|
||||
5. "table" → { type:"table", title:"...", headers:["Col A","Col B"], rows:[["val1","val2"], ...] }
|
||||
6. "cards" → { type:"cards", title:"...", cards:[{title:"Title", description:"Detailed description..."}, ...] }
|
||||
7. "timeline" → { type:"timeline", title:"...", events:[{date:"Jan 2024", title:"Launch", description:"..."}, ...] }
|
||||
8. "quote" → { type:"quote", quote:"Exact quote", author:"Author", context:"Analysis..." }
|
||||
9. "comparison" → { type:"comparison", title:"...", left:{title:"A", points:["..."], score:"8/10"}, right:{title:"B", points:["..."], score:"6/10"} }
|
||||
10. "equation" → { type:"equation", title:"...", equations:[{latex:"E=mc^2", label:"Energy"}], explanation:"..." }
|
||||
11. "image" → { type:"image", title:"...", url:"https://...", caption:"..." }
|
||||
12. "summary" → { type:"summary", title:"...", items:["Key point 1", "Key point 2", ...] }
|
||||
|
||||
═══ RULES ═══
|
||||
- 6 to 12 slides per presentation
|
||||
- Slide 1 MUST be type "title"
|
||||
- Last slide MUST be type "summary"
|
||||
- At least 1 "chart" or "stats" slide if numbers exist in the note
|
||||
- VARY types — never 2 identical types in a row
|
||||
- Each text (bullet, description) = 15+ words, complete sentence
|
||||
- ALL data comes from the note (NEVER invent numbers)
|
||||
- Chart data must reflect actual numbers from the note
|
||||
|
||||
═══ AVAILABLE THEMES ═══
|
||||
Dark: midnight-cathedral, aurora-borealis, tokyo-neon, venture-pitch, forest-floor, steel-glass, cyberpunk-terminal
|
||||
Light: sunlit-gallery, clinical-precision, editorial-ink, coastal-morning, paper-studio, architectural-saas
|
||||
Choose based on topic: business/board → architectural-saas or midnight-cathedral, tech → cyberpunk-terminal or clinical-precision, creative → aurora-borealis or tokyo-neon`,
|
||||
},
|
||||
'task-extractor': {
|
||||
fr: `Tu es un expert en gestion de tâches et extraction d'action items. Tu analyses des notes et documents pour identifier toutes les tâches, TODOs, et actions à accomplir.
|
||||
@@ -1102,21 +1164,46 @@ async function executeToolUseAgent(
|
||||
prompt += `\n\n${lang === 'fr'
|
||||
? 'IMPORTANT : Utilise OBLIGATOIREMENT l\'outil generate_excalidraw pour créer le diagramme. Ne réponds pas avec du texte, appelle directement l\'outil.'
|
||||
: 'IMPORTANT: You MUST use the generate_excalidraw tool to create the diagram. Do NOT respond with text, call the tool directly.'}`
|
||||
const diagramType = agent.slideTheme || 'auto'
|
||||
// Map UI diagram type values to internal tool values
|
||||
const diagramTypeMapping: Record<string, string> = {
|
||||
'mind_map': 'mindmap',
|
||||
'org_chart': 'org-chart',
|
||||
'architecture': 'architecture-cloud',
|
||||
'process_map': 'process-map',
|
||||
'logic_flow': 'auto',
|
||||
}
|
||||
const rawDiagramType = agent.slideTheme || 'auto'
|
||||
const diagramType = diagramTypeMapping[rawDiagramType] || rawDiagramType
|
||||
prompt += `\n\n${lang === 'fr'
|
||||
? `Type de diagramme imposé : ajoute "type":"${diagramType}" dans le JSON envoyé à generate_excalidraw.`
|
||||
: `Required diagram type: include "type":"${diagramType}" in the JSON passed to generate_excalidraw.`}`
|
||||
prompt += `\n\n${lang === 'fr'
|
||||
? 'Types supportés: auto, flowchart, mindmap, architecture-cloud, org-chart, timeline, process-map. Si "auto", choisis selon le métier et le contenu.'
|
||||
: 'Supported types: auto, flowchart, mindmap, architecture-cloud, org-chart, timeline, process-map. If "auto", choose according to domain and content.'}`
|
||||
const diagramStyle = agent.slideStyle === 'austere' || agent.slideStyle === 'sketch-plus' ? agent.slideStyle : 'default'
|
||||
// Map UI diagram style values to internal tool values
|
||||
const diagramStyleMapping: Record<string, string> = {
|
||||
'sketchy': 'sketch-plus',
|
||||
'draft': 'sketch-plus',
|
||||
'handwritten': 'sketch-plus',
|
||||
'minimal': 'austere',
|
||||
'professional': 'austere',
|
||||
'soft': 'default',
|
||||
'polished': 'default',
|
||||
}
|
||||
const rawDiagramStyle = agent.slideStyle || 'default'
|
||||
const diagramStyle = diagramStyleMapping[rawDiagramStyle] || (rawDiagramStyle === 'austere' || rawDiagramStyle === 'sketch-plus' ? rawDiagramStyle : 'default')
|
||||
prompt += `\n\n${lang === 'fr'
|
||||
? `Style visuel imposé : ajoute "style":"${diagramStyle}" dans le JSON envoyé à generate_excalidraw.`
|
||||
: `Visual style required: include "style":"${diagramStyle}" in the JSON passed to generate_excalidraw.`}`
|
||||
break
|
||||
}
|
||||
case 'slide-generator': {
|
||||
const slideTopic = agent.description || agent.name
|
||||
const slideTopic = agent.description?.startsWith('template:')
|
||||
? agent.name
|
||||
: (agent.description || agent.name)
|
||||
const slideTemplate = agent.description?.startsWith('template:')
|
||||
? agent.description.replace('template:', '')
|
||||
: 'auto'
|
||||
const untitled = lang === 'fr' ? 'Sans titre' : 'Untitled'
|
||||
const dateLocale = lang === 'fr' ? 'fr-FR' : 'en-US'
|
||||
let notes: any[] = []
|
||||
@@ -1148,49 +1235,63 @@ async function executeToolUseAgent(
|
||||
}
|
||||
}
|
||||
prompt = lang === 'fr'
|
||||
? `Crée une présentation PowerPoint professionnelle sur le sujet "${slideTopic}" en utilisant le contenu des notes ci-dessous.`
|
||||
: `Create a professional PowerPoint presentation about "${slideTopic}" using the content from the notes below.`
|
||||
? `Crée une présentation professionnelle sur le sujet "${slideTopic}" en utilisant le contenu des notes ci-dessous. Appelle generate_slides avec un objet JSON structuré (title, theme, slides[]).`
|
||||
: `Create a professional presentation about "${slideTopic}" using the content from the notes below. Call generate_slides with a structured JSON object (title, theme, slides[]).`
|
||||
|
||||
// Extract image URLs from note content
|
||||
const extractedImages: Array<{ url: string; noteTitle: string }> = []
|
||||
if (notes.length > 0) {
|
||||
const notesContext = notes.map(n => {
|
||||
// Extract markdown images:  — only external/data URLs (skip relative paths that won't resolve)
|
||||
const mdMatches = [...n.content.matchAll(/!\[[^\]]*\]\((https?:\/\/[^)]+|data:[^)]+)\)/g)]
|
||||
for (const m of mdMatches) {
|
||||
if (m[1]) extractedImages.push({ url: m[1], noteTitle: n.title || untitled })
|
||||
}
|
||||
// Extract HTML img tags
|
||||
const htmlMatches = [...n.content.matchAll(/<img[^>]+src=["'](https?:\/\/[^"']+|data:[^"']+)["']/g)]
|
||||
for (const m of htmlMatches) {
|
||||
if (m[1]) extractedImages.push({ url: m[1], noteTitle: n.title || untitled })
|
||||
}
|
||||
return `### ${n.title || untitled} (${n.createdAt.toLocaleDateString(dateLocale)})\n${n.content.substring(0, 800)}`
|
||||
}).join('\n\n')
|
||||
prompt += `\n\n${lang === 'fr' ? 'Notes source à transformer en slides' : 'Source notes to turn into slides'}:\n\n${notesContext}`
|
||||
const notesContext = notes.map(n =>
|
||||
`### ${n.title || untitled} (${n.createdAt.toLocaleDateString(dateLocale)})\n${n.content.substring(0, 2000)}`
|
||||
).join('\n\n')
|
||||
prompt += `\n\n${lang === 'fr' ? 'Notes source' : 'Source notes'}:\n\n${notesContext}`
|
||||
}
|
||||
|
||||
// Inject available images into the prompt
|
||||
const uniqueImages = extractedImages.slice(0, 6) // max 6 images
|
||||
if (uniqueImages.length > 0) {
|
||||
const imgList = uniqueImages.map((img, i) => ` ${i + 1}. "${img.noteTitle}" → ${img.url.substring(0, 120)}`).join('\n')
|
||||
prompt += `\n\n${lang === 'fr'
|
||||
? `IMAGES DISPONIBLES (extraites des notes) — utilise-les dans le JSON via le champ "imageUrl" avec le layout "image-content" ou "image-full" :\n${imgList}`
|
||||
: `AVAILABLE IMAGES (extracted from notes) — use them in the JSON via the "imageUrl" field with layout "image-content" or "image-full":\n${imgList}`}`
|
||||
// ── Executive Template Structure (HTML-compatible) ──
|
||||
if (slideTemplate && slideTemplate !== 'auto') {
|
||||
const templates: Record<string, { fr: string; en: string }> = {
|
||||
'board-update': {
|
||||
fr: `Structure imposée "Board Update" (10 slides) :
|
||||
1. TITRE avec date | 2. KPIs majeurs (3-4 gros chiffres) | 3. Bar chart progression objectifs | 4. Grille de métriques (6 cards) | 5. Timeline jalons | 6. Cards réalisations | 7. Line chart tendance | 8. Deux colonnes risques/mitigations | 9. Bullets prochaines étapes | 10. Conclusion`,
|
||||
en: `Mandatory "Board Update" structure (10 slides):
|
||||
1. TITLE with date | 2. Key KPIs (3-4 big numbers) | 3. Bar chart goal progress | 4. Metrics grid (6 cards) | 5. Timeline milestones | 6. Achievement cards | 7. Line chart trend | 8. Two-column risks/mitigations | 9. Next steps bullets | 10. Conclusion`
|
||||
},
|
||||
'project-status': {
|
||||
fr: `Structure imposée "Project Status" (10 slides) :
|
||||
1. TITRE + statut 🟢🟡🔴 | 2. KPIs (% avancement, jours, budget) | 3. Bar chart par workstream | 4. Cards livrables | 5. Timeline roadmap | 6. Line chart burn-down | 7. Deux colonnes blockers/actions | 8. Tableau de risques | 9. Bullets décisions requises | 10. Synthèse`,
|
||||
en: `Mandatory "Project Status" structure (10 slides):
|
||||
1. TITLE + status 🟢🟡🔴 | 2. KPIs (% complete, days, budget) | 3. Bar chart by workstream | 4. Deliverable cards | 5. Timeline roadmap | 6. Line chart burn-down | 7. Two-column blockers/actions | 8. Risk table | 9. Required decisions bullets | 10. Summary`
|
||||
},
|
||||
'strategy-review': {
|
||||
fr: `Structure imposée "Strategy Review" (10 slides) :
|
||||
1. TITRE stratégique | 2. Contexte marché (5+ bullets) | 3. Radar/pie positionnement | 4. SWOT deux colonnes | 5. Area chart tendances | 6. Cards axes stratégiques | 7. Timeline roadmap 12 mois | 8. Bar chart projections | 9. KPIs objectifs cibles | 10. Call to action`,
|
||||
en: `Mandatory "Strategy Review" structure (10 slides):
|
||||
1. Strategic TITLE | 2. Market context (5+ bullets) | 3. Radar/pie positioning | 4. SWOT two-column | 5. Area chart trends | 6. Strategic axes cards | 7. 12-month roadmap timeline | 8. Bar chart projections | 9. Target KPIs | 10. Call to action`
|
||||
},
|
||||
'quarterly-results': {
|
||||
fr: `Structure imposée "Quarterly Results" (10 slides) :
|
||||
1. TITRE "Résultats Q? Année" | 2. 4 KPIs (Revenue, Croissance, Marge, NPS) | 3. Bar chart revenue/mois | 4. Line chart croissance YoY | 5. Cards faits marquants | 6. Grille métriques opérationnelles | 7. Donut répartition clients | 8. Deux colonnes succès/challenges | 9. Area chart forecast | 10. Conclusion outlook`,
|
||||
en: `Mandatory "Quarterly Results" structure (10 slides):
|
||||
1. TITLE "Q? Year Results" | 2. 4 KPIs (Revenue, Growth, Margin, NPS) | 3. Bar chart revenue/month | 4. Line chart YoY growth | 5. Highlights cards | 6. Operational metrics grid | 7. Donut client breakdown | 8. Two-column successes/challenges | 9. Area chart forecast | 10. Conclusion outlook`
|
||||
}
|
||||
}
|
||||
const tmpl = templates[slideTemplate]
|
||||
if (tmpl) {
|
||||
prompt += `\n\n${tmpl[lang === 'fr' ? 'fr' : 'en']}`
|
||||
}
|
||||
}
|
||||
|
||||
// ── Density rules ──
|
||||
prompt += lang === 'fr'
|
||||
? `\n\nDENSITÉ OBLIGATOIRE : Chaque slide doit avoir un CONTENU RICHE. Minimum 5 bullets par slide "bullets" (≥15 mots chaque). Minimum 4 cards quand tu fais "cards". Minimum 4 data points quand tu fais "chart". Inclus OBLIGATOIREMENT au moins 1 slide "chart" avec données RÉELLES extraites des notes. Si pas de chiffres dans la note, fais un radar de maturité ou une comparaison qualitative notée sur 5.`
|
||||
: `\n\nMANDATORY DENSITY: Every slide must have RICH CONTENT. Minimum 5 items per "bullets" slide (≥15 words each). Minimum 4 cards when using "cards". Minimum 4 data points for "chart". You MUST include at least 1 "chart" slide with REAL data from the notes. If no numbers in notes, create a maturity radar or qualitative comparison scored out of 5.`
|
||||
|
||||
prompt += `\n\n${lang === 'fr'
|
||||
? 'IMPORTANT : Appelle OBLIGATOIREMENT generate_pptx. Ne réponds pas avec du texte. Crée 8-12 slides visuelles, commence par "title", puis "toc", intègre AU MOINS 2 layouts diagramme (timeline, process, metrics, ou comparison). Évite les slides avec juste du texte — favorise les layouts visuels.'
|
||||
: 'IMPORTANT: You MUST call generate_pptx. Do NOT respond with text. Create 8-12 visual slides: start with "title", then "toc", include AT LEAST 2 diagram layouts (timeline, process, metrics, or comparison). Avoid text-only slides — prefer visual layouts.'}`
|
||||
if (agent.slideTheme) {
|
||||
prompt += `\n\n${lang === 'fr'
|
||||
? `Thème imposé par l'utilisateur : "${agent.slideTheme}". Dans le JSON tu DOIS mettre "theme": "${agent.slideTheme}".`
|
||||
: `User-selected theme: "${agent.slideTheme}". You MUST put "theme": "${agent.slideTheme}" in the JSON.`}`
|
||||
}
|
||||
if (agent.slideStyle) {
|
||||
? 'IMPORTANT : Appelle OBLIGATOIREMENT generate_slides avec le JSON structuré {title, theme, slides:[...]}. Ne réponds JAMAIS avec du texte brut. 6-12 slides variées.'
|
||||
: 'IMPORTANT: You MUST call generate_slides with structured JSON {title, theme, slides:[...]}. NEVER respond with plain text. 6-12 varied slides.'}`
|
||||
|
||||
if (agent.slideTheme && agent.slideTheme !== 'auto') {
|
||||
prompt += `\n${lang === 'fr'
|
||||
? `Style visuel imposé : dans le JSON tu DOIS mettre "style": "${agent.slideStyle}". Les valeurs possibles sont: "sharp" (angles nets), "soft" (arrondi standard), "rounded" (très arrondi), "pill" (capsules).`
|
||||
: `Visual style: you MUST put "style": "${agent.slideStyle}" in the JSON. Values: "sharp" (crisp edges), "soft" (standard rounded), "rounded" (very rounded), "pill" (capsule shapes).`}`
|
||||
? `Thème visuel imposé : utilise "theme":"${agent.slideTheme}" dans l'appel generate_slides.`
|
||||
: `Visual theme required: use "theme":"${agent.slideTheme}" in the generate_slides call.`}`
|
||||
}
|
||||
break
|
||||
}
|
||||
@@ -1269,7 +1370,7 @@ async function executeToolUseAgent(
|
||||
return { success: false, actionId, error: 'Model does not support tool calling' }
|
||||
}
|
||||
if (agentType === 'slide-generator' || agentType === 'excalidraw-generator') {
|
||||
const toolName = agentType === 'slide-generator' ? 'generate_pptx' : 'generate_excalidraw'
|
||||
const toolName = agentType === 'slide-generator' ? 'generate_slides' : 'generate_excalidraw'
|
||||
await prisma.agentAction.update({
|
||||
where: { id: actionId },
|
||||
data: {
|
||||
@@ -1301,7 +1402,7 @@ async function executeToolUseAgent(
|
||||
const scrapedUrls: string[] = []
|
||||
let specificToolCalled = false
|
||||
const requiredTool = isFileGenerator
|
||||
? (agentType === 'slide-generator' ? ['generate_pptx'] : ['generate_excalidraw'])
|
||||
? (agentType === 'slide-generator' ? ['generate_slides'] : ['generate_excalidraw'])
|
||||
: null
|
||||
|
||||
for (const step of result.steps) {
|
||||
@@ -1312,7 +1413,7 @@ async function executeToolUseAgent(
|
||||
existingNoteId = toolResult.output.noteId
|
||||
}
|
||||
}
|
||||
if (step.toolCalls[i].toolName === 'generate_excalidraw' || step.toolCalls[i].toolName === 'generate_slides' || step.toolCalls[i].toolName === 'generate_pptx') {
|
||||
if (step.toolCalls[i].toolName === 'generate_excalidraw' || step.toolCalls[i].toolName === 'generate_slides') {
|
||||
const toolResult = step.toolResults?.[i]
|
||||
if (toolResult && typeof toolResult.output === 'object' && toolResult.output?.success && toolResult.output?.canvasId) {
|
||||
canvasId = toolResult.output.canvasId as string
|
||||
|
||||
Reference in New Issue
Block a user