{
  "name": "Veille CGP — Perplexity (vendredi 8h)",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 8 * * 5"
            }
          ]
        }
      },
      "id": "c1111111-0000-0000-0000-000000000001",
      "name": "Déclencheur vendredi 8h",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [448, 80],
      "notes": "Hebdomadaire (vendredi uniquement). GENERIC_TIMEZONE doit être Europe/Paris sur l'instance. Périmètres 3 (réglementaire CGP) et 4 (actu métier CGP) — cf. UKP-PERPLEXITY-VEILLE.md."
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.perplexity.ai/chat/completions",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "perplexityApi",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({\n  model: \"sonar-pro\",\n  messages: [\n    {\n      role: \"system\",\n      content: \"Tu es un assistant de veille documentaire pour Fidulia, agence LinkedIn spécialisée dans l'accompagnement des Conseillers en Gestion de Patrimoine (CGP) indépendants. Réponds UNIQUEMENT par un JSON valide, sans aucun texte autour, au format exact : {\\\"items\\\":[{\\\"title\\\":\\\"...\\\",\\\"url\\\":\\\"...\\\",\\\"source\\\":\\\"...\\\",\\\"date\\\":\\\"YYYY-MM-DD\\\",\\\"summary\\\":\\\"...\\\"}]}. Chaque item doit être un fait vérifiable et sourcé, jamais une opinion. Si aucune actualité pertinente n'est trouvée, renvoie {\\\"items\\\":[]} plutôt que d'inventer un item.\"\n    },\n    {\n      role: \"user\",\n      content: \"Recherche les actualités réglementaires et professionnelles les plus importantes pour les Conseillers en Gestion de Patrimoine (CGP) publiées durant les 7 derniers jours, uniquement sur ces sites : amf-france.org, acpr.banque-france.fr, orias.fr, cncgp.fr, anacofi.asso.fr, agefi.fr, patrimoine.lesechos.fr, optionfinance.fr, professioncgp.com, clubpatrimoine.com, aurep.com, citywire.com. Maximum 8 items.\"\n    }\n  ],\n  search_domain_filter: [\"amf-france.org\",\"acpr.banque-france.fr\",\"orias.fr\",\"cncgp.fr\",\"anacofi.asso.fr\",\"agefi.fr\",\"patrimoine.lesechos.fr\",\"optionfinance.fr\",\"professioncgp.com\",\"clubpatrimoine.com\",\"aurep.com\",\"citywire.com\"],\n  search_recency_filter: \"week\",\n  return_citations: true\n}) }}",
        "options": {
          "timeout": 300000
        }
      },
      "id": "c1111111-0000-0000-0000-000000000002",
      "name": "Perplexity — Sonar Pro (12 sources CGP)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [672, 80],
      "credentials": {
        "perplexityApi": {
          "id": "jsNGbD5FFfiFzNuF",
          "name": "Perplexity account"
        }
      },
      "notes": "Credential natif 'Perplexity API' (type prédéfini, pas Generic/Header Auth — n8n gère l'en-tête Authorization en interne à partir du champ API Key). Timeout 300000ms (5 min) : aligné sur le timeout Apify existant, suffisant même en cas de latence Sonar-Pro. search_domain_filter restreint strictement aux 12 sources validées dans SOURCES.md. Format de sortie forcé en JSON strict pour un parsing déterministe en aval (cf. UKP-PROMPTING.md — toujours préciser le format de sortie)."
    },
    {
      "parameters": {
        "jsCode": "// Parse la réponse Sonar (JSON strict demandé dans le prompt système) et la met à plat\n// en une ligne par item, prête pour la file 'CGP-Perplexity'.\nconst runDate = new Date().toISOString().slice(0, 10);\nconst runId = new Date().toISOString();\n\nconst body = $input.first().json;\nconst raw = body?.choices?.[0]?.message?.content || '{}';\n\nlet parsed;\ntry {\n  parsed = JSON.parse(raw);\n} catch (e) {\n  // Fallback : le modèle a parfois entouré le JSON de texte malgré la consigne.\n  const match = String(raw).match(/\\{[\\s\\S]*\\}/);\n  parsed = match ? JSON.parse(match[0]) : { items: [] };\n}\n\nconst items = Array.isArray(parsed.items) ? parsed.items : [];\nif (items.length === 0) return [];\n\nreturn items.map((it, idx) => ({\n  json: {\n    itemId: `${runId}-${idx}`,\n    runDate,\n    runId,\n    title: it.title || '',\n    url: it.url || '',\n    source: it.source || '',\n    date: it.date || '',\n    summary: it.summary || '',\n    statut: 'PENDING',\n    traitePar: '',\n    dateTraitement: ''\n  }\n}));"
      },
      "id": "c1111111-0000-0000-0000-000000000003",
      "name": "Parser réponse Perplexity",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [896, 80],
      "notes": "Retry on Fail à activer sur le nœud HTTP Request précédent (3 tentatives / 2s) — cf. UKP-N8N-FONDAMENTAUX Axe 4. Si items vide (aucune actu pertinente cette semaine), le workflow s'arrête proprement ici, rien n'est écrit dans la Sheet."
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": {
          "__rl": true,
          "value": "1NvgtiwfgwKRjsm025O3qlXnUcw6QffZpVLI1_4IAHLc",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "CGP-Perplexity",
          "mode": "name"
        },
        "columns": {
          "mappingMode": "autoMapInputData",
          "matchingColumns": [],
          "value": {}
        },
        "options": {}
      },
      "id": "c1111111-0000-0000-0000-000000000004",
      "name": "Écrire file CGP-Perplexity (PENDING)",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [1120, 80],
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "EvORDqxqhAIKRlIW",
          "name": "Google Sheets account"
        }
      },
      "notes": "Nouvel onglet 'CGP-Perplexity' à créer dans le classeur existant (ID 1Nvg...). Colonnes (ligne 1) : itemId | runDate | runId | title | url | source | date | summary | statut | traitePar | dateTraitement. itemId est la clé unique par ligne (runId-index) — nécessaire car un run produit plusieurs items et la mise à jour DONE doit pouvoir cibler chaque ligne individuellement (le nœud Google Sheets appendOrUpdate ne met à jour qu'une ligne par valeur de clé de correspondance). La routine locale ROUTINE-VEILLE-CGP-HEBDO.md lit les lignes statut=PENDING."
    }
  ],
  "connections": {
    "Déclencheur vendredi 8h": {
      "main": [[{ "node": "Perplexity — Sonar Pro (12 sources CGP)", "type": "main", "index": 0 }]]
    },
    "Perplexity — Sonar Pro (12 sources CGP)": {
      "main": [[{ "node": "Parser réponse Perplexity", "type": "main", "index": 0 }]]
    },
    "Parser réponse Perplexity": {
      "main": [[{ "node": "Écrire file CGP-Perplexity (PENDING)", "type": "main", "index": 0 }]]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "active": false,
  "pinData": {},
  "meta": {
    "instanceId": "4f1b23afe1c1f425a998bc69ab78d2ebd64d2175c452226921ae034356fabed4"
  }
}
