PageSourceSearch

https://creaconnect.world/src/crea-sources.js

js creaconnect.world collected 2026-09-24 10:10:19 UTC 18,997 bytes, 228 lines download raw bytes

1/* ============================================================
2 * CREA SOURCES — TOUS les outils & ressources du réel, par domaine et sous-domaine.
3 * Pour que Créa (et les agents/DLM) s'appuient sur le réel au lieu d'inventer.
4 *
5 *  • OUTILS (services live) par domaine : heure mondiale, météo, géocodage, change,
6 *    cartes, actualités, traduction, QR, Bible… (les sans-clé marchent côté client).
7 *  • RESSOURCES (savoir) par domaine→sous-domaine : Wikipedia, Wikidata, arXiv, PubMed,
8 *    Légifrance, Service-Public, World Bank, Gutenberg, Open Library, NASA, Gallica…
9 *  • Awareness injectée (routée par domaine = peu de tokens) : Créa sait OÙ puiser.
10 *  • Outil sans-clé câblé en direct : taux de change (open.er-api.com).
11 *
12 * 100% autonome. Charge APRÈS app.js. Expose window.CREA_SOURCES.
13 * ============================================================ */
14;(function () {
15  'use strict'
16  if (window.CREA_SOURCES) return
17  function lc(s) { return String(s || '').toLowerCase() }
18  function esc(s) { return String(s == null ? '' : s).replace(/[&<>"']/g, function (c) { return ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' })[c] }) }
19
20  // Indice de confiance : 5=institution officielle/scientifique · 4=encyclopédique curé · 3=agrégateur qualité · 2=live/flux · 1=non vérifié
21  var TRUST_STARS = { 5: '⭐⭐⭐⭐⭐', 4: '⭐⭐⭐⭐', 3: '⭐⭐⭐', 2: '⭐⭐', 1: '⭐' }
22  var TRUST_LABELS = { 5: 'institution officielle', 4: 'encyclopédie curée', 3: 'agrégateur qualité', 2: 'flux live', 1: 'non vérifié' }
23
24  // ---- OUTILS LIVE par domaine ----
25  var TOOLS = [
26    { d: 'Temps',       icon: '🕐', name: 'Heure & date mondiales',         src: 'horloge système + WorldTimeAPI',      trust: 4, live: true },
27    { d: 'Météo',       icon: '⛅', name: 'Météo locale',                   src: 'Open-Meteo (sans clé)',               trust: 3, live: true },
28    { d: 'Localisation',icon: '📍', name: 'Ville & adresse exactes',        src: 'Nominatim/OSM + BigDataCloud',        trust: 4, live: true },
29    { d: 'Finance',     icon: '💱', name: 'Taux de change',                 src: 'open.er-api.com (sans clé)',          trust: 3, live: true },
30    { d: 'Cartes',      icon: '🗺️', name: 'Cartes & itinéraires',          src: 'OpenStreetMap / OSRM',                trust: 4 },
31    { d: 'Actualités',  icon: '📰', name: 'Actualités (mondiales & locales)',src: 'flux RSS / recherche web',            trust: 2 },
32    { d: 'Langues',     icon: '🌐', name: 'Traduction',                     src: 'LibreTranslate',                      trust: 3 },
33    { d: 'Web',         icon: '🔎', name: 'Recherche & lecture de pages',   src: '/api/search · /api/browse',           trust: 2 },
34    { d: 'Foi',         icon: '✝️', name: 'Bible',                         src: 'LSG embarquée + /api/bible',          trust: 5 },
35    { d: 'Utilitaires', icon: '🔳', name: 'QR codes',                       src: '/api/qr',                             trust: 5 },
36    { d: 'Démarches',   icon: '🏛️', name: 'Service-Public / France Connect',src: 'flux officiel (consentement)',       trust: 5 }
37  ]
38
39  // ---- RESSOURCES (savoir) par domaine → sous-domaines → sources fiables ----
40  var RES = [
41    { d: 'Général',          icon: '📚', sub: 'tout sujet',                   sources: 'Wikipedia · Wikidata',                      trust: 4 },
42    { d: 'Science',          icon: '🔬', sub: 'physique, chimie, biologie, IA',sources: 'arXiv · Wikipedia · Semantic Scholar',       trust: 4 },
43    { d: 'Mathématiques',    icon: '➗', sub: 'algèbre, analyse, stats',       sources: 'Wikipedia · OEIS · Wolfram',                trust: 4 },
44    { d: 'Santé',            icon: '❤️', sub: 'maladies, prévention, nutrition',sources: 'PubMed · MedlinePlus · OMS (jamais un diagnostic)', trust: 5 },
45    { d: 'Droit',            icon: '⚖️', sub: 'lois, contrats, RGPD (FR)',    sources: 'Légifrance · Service-Public.fr · EUR-Lex',  trust: 5 },
46    { d: 'Économie',         icon: '💰', sub: 'macro, marché, fiscalité',      sources: 'World Bank · INSEE · OCDE · taux de change', trust: 4 },
47    { d: 'Histoire & Culture',icon: '🏛️',sub: 'histoire, arts, patrimoine',   sources: 'Wikipedia · Gallica (BnF) · Europeana',     trust: 4 },
48    { d: 'Géographie',       icon: '🌍', sub: 'pays, villes, cartes',          sources: 'OpenStreetMap · Wikidata · GeoNames',       trust: 4 },
49    { d: 'Livres & Littérature',icon:'📖',sub: 'œuvres, citations',            sources: 'Project Gutenberg · Open Library',          trust: 4 },
50    { d: 'Technologie & Code',icon: '💻',sub: 'langages, frameworks, API',     sources: 'MDN · docs officielles · Wikipedia',        trust: 4 },
51    { d: 'Astronomie & Espace',icon:'🪐',sub: 'planètes, missions',            sources: 'NASA APIs · Wikipedia',                     trust: 5 },
52    { d: 'Environnement',    icon: '🌱', sub: 'climat, biodiversité, énergie', sources: 'GIEC · Our World in Data',                  trust: 5 },
53    { d: 'Foi & Bible',      icon: '✝️', sub: 'Écritures, thèmes, versets',   sources: 'Bible LSG (domaine public) · /api/bible',   trust: 5 },
54    { d: 'Actualités',       icon: '📰', sub: 'événements récents',            sources: 'recherche web (toujours daté & vérifié)',    trust: 2 }
55  ]
56
57  // Retourne l'indice de confiance (1-5) pour une source nommée (correspondance partielle)
58  function trustFor(sourceName) {
59    if (!sourceName) return 2
60    var q = String(sourceName).toLowerCase()
61    var all = TOOLS.concat(RES)
62    for (var i = 0; i < all.length; i++) {
63      var item = all[i]
64      if ((item.src || item.sources || '').toLowerCase().indexOf(q) >= 0 ||
65          (item.name || item.d || '').toLowerCase().indexOf(q) >= 0) {
66        return item.trust || 3
67      }
68    }
69    // Heuristiques rapides
70    if (/pubmed|medline|oms|legifrance|service-public|nasa|giec|insee|eur-lex/i.test(q)) return 5
71    if (/wikipedia|wikidata|arxiv|openstreetmap|europeana/i.test(q)) return 4
72    if (/world.bank|ocde|open.meteo|gutenberg/i.test(q)) return 3
73    if (/gdelt|rss|twitter|flux|web/i.test(q)) return 2
74    return 3
75  }
76
77  function domainsFor(q) {
78    q = lc(q)
79    var map = {
80      science: 'Science', physique: 'Science', chimie: 'Science', biologie: 'Science', recherche: 'Science', étude: 'Science', photosynth: 'Science', cellule: 'Science', neuro: 'Science',
81      math: 'Mathématiques', équation: 'Mathématiques', calcul: 'Mathématiques', algèbre: 'Mathématiques', statistique: 'Mathématiques',
82      santé: 'Santé', maladie: 'Santé', symptôme: 'Santé', médic: 'Santé', nutrition: 'Santé', sommeil: 'Santé', vitamine: 'Santé',
83      droit: 'Droit', loi: 'Droit', contrat: 'Droit', rgpd: 'Droit', juridique: 'Droit', démarche: 'Droit',
84      économie: 'Économie', argent: 'Économie', fiscal: 'Économie', impôt: 'Économie', bourse: 'Économie', inflation: 'Économie', taux: 'Économie', change: 'Économie',
85      histoire: 'Histoire & Culture', guerre: 'Histoire & Culture', art: 'Histoire & Culture', musique: 'Histoire & Culture', peinture: 'Histoire & Culture',
86      pays: 'Géographie', ville: 'Géographie', capitale: 'Géographie', population: 'Géographie', carte: 'Géographie',
87      livre: 'Livres & Littérature', roman: 'Livres & Littérature', auteur: 'Livres & Littérature', citation: 'Livres & Littérature', poème: 'Livres & Littérature',
88      code: 'Technologie & Code', python: 'Technologie & Code', javascript: 'Technologie & Code', api: 'Technologie & Code', serveur: 'Technologie & Code',
89      planète: 'Astronomie & Espace', espace: 'Astronomie & Espace', étoile: 'Astronomie & Espace', nasa: 'Astronomie & Espace', galaxie: 'Astronomie & Espace',
90      climat: 'Environnement', co2: 'Environnement', énergie: 'Environnement', biodiversité: 'Environnement', réchauffement: 'Environnement',
91      bible: 'Foi & Bible', dieu: 'Foi & Bible', jésus: 'Foi & Bible', verset: 'Foi & Bible', prière: 'Foi & Bible',
92      actualité: 'Actualités', news: 'Actualités', récent: 'Actualités', aujourd: 'Actualités'
93    }
94    /* ── UN MOT, PAS UNE SUITE DE LETTRES ────────────────────────────────
95     *
96     * `q.indexOf(k) >= 0` attrapait le mot-clé PARTOUT, y compris au milieu
97     * d'un autre mot. Mesuré sur dix demandes ordinaires de CRÉA : NEUF
98     * réveillaient un domaine qu'elles ne concernent pas.
99     *
100     *     « quelle est la cAPItale du Pérou »   → Technologie & Code
101     *     « fais un résumé rAPIde »             → Technologie & Code
102     *     « écris le chAPItre 3 »               → Technologie & Code
103     *     « déCODE ce message »                 → Technologie & Code
104     *     « relis le PAYSage concurrentiel »    → Géographie
105     *     « calCULe le coût »                   → Mathématiques
106     *
107     * Le bloc a l'air conditionnel et partait sur presque tout : cinq cents
108     * caractères de sources hors sujet, à chaque message. C'est exactement le
109     * bloc que la règle du terrain interdit, déguisé en bloc jugé.
110     *
111     * `\b` NE MARCHE PAS ICI : les bornes de mot de JavaScript sont ASCII, et
112     * `é`, `è`, `ô` n'en sont pas. On borne donc sur « pas une lettre et pas un
113     * chiffre », en Unicode (`\p{L}`, drapeau `u`) — la même forme que les
114     * terrains de `crea-access.js`.
115     *
116     * ET LA BORNE DE DROITE TOLÈRE UNE LETTRE, pas trois : « cartes » et
117     * « calcule » doivent mordre, « paysage » ne doit pas. Trois lettres
118     * ramèneraient « paysage ».
119     *
120     * CINQ CLÉS SONT DES RACINES, PAS DES MOTS — `photosynth`, `médic`,
121     * `neuro`, `fiscal`, `aujourd`. Elles sont écrites pour attraper
122     * « photosynthèse », « médicament », « aujourd'hui » : leur imposer une
123     * borne à droite les rendrait muettes. Elles sont nommées ici, pas
124     * devinées, parce qu'une racine et un mot ne se distinguent pas à l'œil. */
125    var RACINES = { photosynth: 1, 'médic': 1, neuro: 1, fiscal: 1, aujourd: 1 }
126    var hit = {}
127    Object.keys(map).forEach(function (k) {
128      var m = k.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
129      var motif = '(?:^|[^\\p{L}\\p{N}])' + m + (RACINES[k] ? '' : '(?:[se])?(?![\\p{L}\\p{N}])')
130      try { if (new RegExp(motif, 'iu').test(q)) hit[map[k]] = 1 }
131      catch (e) { if (q.indexOf(k) >= 0) hit[map[k]] = 1 /* moteur sans \p{L} : l'ancien comportement plutôt qu'un domaine perdu */ }
132    })
133    return Object.keys(hit)
134  }
135
136  /* ── LA DEMANDE ARRIVE EN ARGUMENT ───────────────────────────────────────
137   *
138   * Ce poste allait CHERCHER lui-même le dernier message du fil de chat. C'est
139   * le défaut que le dépôt a déjà payé sur la gorge, et qui est écrit dans
140   * CLAUDE.md : « dans le chat, la même phrase, invisible ; dans les douze
141   * studios, la mauvaise ». Mesuré ici, avec un fil qui parle du Pérou pendant
142   * qu'un studio demande un script Python : le bloc rendait les sources de la
143   * GÉOGRAPHIE.
144   *
145   * Viser la mauvaise phrase ne décale pas un bloc jugé : ça le fait mentir.
146   * La demande vient donc de l'appelant — la gorge la lui passe, comme à tous
147   * les autres postes. Une chaîne vide veut dire « pas de demande » : le bloc
148   * se tait, il n'hérite de rien. */
149  function contextBlock(demande) {
150    var q = String(demande == null ? '' : demande)
151    var doms = domainsFor(q); if (!doms.length) return ''
152    var lines = doms.map(function (d) { var r = RES.find(function (x) { return x.d === d }); return r ? ('• ' + r.d + ' [confiance ' + (r.trust||3) + '/5] → ' + r.sources) : null }).filter(Boolean)
153    if (!lines.length) return ''
154    return '=== SOURCES FIABLES PAR DOMAINE (puise ici, vérifie, CITE — n\'invente pas) ===\n' + lines.join('\n') +
155      '\nLégende confiance : 5=institution officielle · 4=encyclopédie curée · 3=agrégateur · 2=flux live · 1=non vérifié' +
156      '\nUtilise la recherche web pour atteindre ces sources, donne des faits datés, et termine par Sources · Limites quand c\'est important.\n\n'
157  }
158
159  /* ---- outil live câblé : taux de change (sans clé) ---- */
160  function rate(from, to) {
161    return fetch('https://open.er-api.com/v6/latest/' + encodeURIComponent((from || 'EUR').toUpperCase()))
162      .then(function (r) { return r.ok ? r.json() : null })
163      .then(function (j) { return (j && j.rates && j.rates[(to || 'USD').toUpperCase()]) || null })
164      .catch(function () { return null })
165  }
166
167  function open() {
168    var old = document.getElementById('crea-sources'); if (old) { old.remove(); return }
169    var ov = document.createElement('div'); ov.id = 'crea-sources'
170    var tools = TOOLS.map(function (t) { return '<div class="cs4-row"><span class="cs4-ic">' + t.icon + '</span><div class="cs4-tx"><b>' + esc(t.name) + '</b><span>' + esc(t.d) + ' · ' + esc(t.src) + '</span></div>' + (t.live ? '<span class="cs4-live">● live</span>' : '<span class="cs4-soon">via web</span>') + '</div>' }).join('')
171    var res = RES.map(function (r) { return '<div class="cs4-row"><span class="cs4-ic">' + r.icon + '</span><div class="cs4-tx"><b>' + esc(r.d) + '</b><span>' + esc(r.sub) + ' — ' + esc(r.sources) + '</span></div></div>' }).join('')
172    ov.innerHTML = '<div class="cs4-box"><div class="cs4-head"><span>🧭 Outils & ressources du réel (tout domaine)</span><button class="cs4-x" data-close>✕</button></div>' +
173      '<div class="cs4-note">Créa s\'appuie sur ces sources réelles selon le domaine de ta question, au lieu d\'inventer — et il les cite.</div>' +
174      '<div class="cs4-t">🔧 Outils live</div><div class="cs4-list">' + tools + '</div>' +
175      '<div class="cs4-t">📚 Ressources de savoir par domaine</div><div class="cs4-list">' + res + '</div></div>'
176    document.body.appendChild(ov)
177    ov.addEventListener('mousedown', function (e) { if (e.target === ov) ov.remove() })
178    ov.addEventListener('click', function (e) { if (e.target.closest('[data-close]')) ov.remove() })
179    document.addEventListener('keydown', function onEsc(e) { if (e.key === 'Escape') { ov.remove(); document.removeEventListener('keydown', onEsc) } })
180  }
181
182  function css() {
183    if (document.getElementById('crea-sources-css')) return
184    var s = document.createElement('style'); s.id = 'crea-sources-css'
185    s.textContent =
186      '#crea-sources{position:fixed;inset:0;z-index:90020;background:rgba(0,0,0,.5);backdrop-filter:blur(3px);display:flex;align-items:center;justify-content:center;padding:16px}' +
187      '#crea-sources .cs4-box{width:min(620px,96vw);max-height:88vh;overflow-y:auto;background:var(--bg-secondary,#161616);border:1px solid var(--border,#333);border-radius:18px;box-shadow:0 24px 70px rgba(0,0,0,.5)}' +
188      '#crea-sources .cs4-head{display:flex;align-items:center;padding:15px 18px;border-bottom:1px solid var(--border,#333);position:sticky;top:0;background:var(--bg-secondary,#161616)}' +
189      '#crea-sources .cs4-head span{flex:1;color:var(--t-primary,#eee);font:700 14px Inter,system-ui,sans-serif}' +
190      '#crea-sources .cs4-x{background:none;border:0;color:var(--t-faint,#999);font-size:16px;cursor:pointer}' +
191      '#crea-sources .cs4-note{padding:12px 18px;color:var(--t-secondary,#bbb);font:500 12px/1.5 Inter;border-bottom:1px solid var(--border,#2a2a2a)}' +
192      '#crea-sources .cs4-t{color:var(--t-faint,#888);font:600 10px Inter;text-transform:uppercase;letter-spacing:.05em;padding:13px 18px 4px}' +
193      '#crea-sources .cs4-list{padding:0 12px 6px}' +
194      '#crea-sources .cs4-row{display:flex;align-items:center;gap:10px;padding:8px 8px;border-radius:10px}' +
195      '#crea-sources .cs4-row:hover{background:var(--bg-hover,rgba(255,255,255,.03))}' +
196      '#crea-sources .cs4-ic{font-size:16px;width:22px;text-align:center}' +
197      '#crea-sources .cs4-tx{flex:1;min-width:0}#crea-sources .cs4-tx b{display:block;color:var(--t-primary,#eee);font:600 12.5px Inter}#crea-sources .cs4-tx span{color:var(--t-faint,#888);font:500 11px Inter}' +
198      '#crea-sources .cs4-live{color:#10a37f;font:700 10px Inter;flex:0 0 auto}#crea-sources .cs4-soon{color:var(--t-faint,#888);font:600 10px Inter;flex:0 0 auto}' +
199      '#crea-sources .cs4-trust{font:600 9px Inter;flex:0 0 auto;opacity:.75;letter-spacing:.03em}'
200    document.head.appendChild(s)
201  }
202  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', css); else css()
203
204  // Update panel render to show trust scores
205  var _origOpen = open
206  open = function () {
207    var old = document.getElementById('crea-sources'); if (old) { old.remove(); return }
208    css()
209    var ov = document.createElement('div'); ov.id = 'crea-sources'
210    function trustBadge(t) {
211      var stars = ['', '★', '★★', '★★★', '★★★★', '★★★★★'][t || 3] || '★★★'
212      var color = ['', '#dc2626', '#d97706', '#2563eb', '#059669', '#10a37f'][t || 3] || '#2563eb'
213      return '<span class="cs4-trust" style="color:' + color + '">' + stars + '</span>'
214    }
215    var tools = TOOLS.map(function (t) { return '<div class="cs4-row"><span class="cs4-ic">' + t.icon + '</span><div class="cs4-tx"><b>' + esc(t.name) + '</b><span>' + esc(t.d) + ' · ' + esc(t.src) + '</span></div>' + trustBadge(t.trust) + (t.live ? '<span class="cs4-live">● live</span>' : '<span class="cs4-soon">via web</span>') + '</div>' }).join('')
216    var res = RES.map(function (r) { return '<div class="cs4-row"><span class="cs4-ic">' + r.icon + '</span><div class="cs4-tx"><b>' + esc(r.d) + '</b><span>' + esc(r.sub) + ' — ' + esc(r.sources) + '</span></div>' + trustBadge(r.trust) + '</div>' }).join('')
217    ov.innerHTML = '<div class="cs4-box"><div class="cs4-head"><span>🧭 Outils & ressources du réel (tout domaine)</span>
217<button class="cs4-x" data-close>✕</button></div>' +
218      '<div class="cs4-note">Créa s\'appuie sur ces sources selon le domaine, les cite, et indique leur indice de confiance (★ à ★★★★★).</div>' +
219      '<div class="cs4-t">🔧 Outils live</div><div class="cs4-list">' + tools + '</div>' +
220      '<div class="cs4-t">📚 Ressources de savoir par domaine</div><div class="cs4-list">' + res + '</div></div>'
221    document.body.appendChild(ov)
222    ov.addEventListener('mousedown', function (e) { if (e.target === ov) ov.remove() })
223    ov.addEventListener('click', function (e) { if (e.target.closest('[data-close]')) ov.remove() })
224    document.addEventListener('keydown', function onEsc(e) { if (e.key === 'Escape') { ov.remove(); document.removeEventListener('keydown', onEsc) } })
225  }
226
227  window.CREA_SOURCES = { TOOLS: TOOLS, RES: RES, domainsFor: domainsFor, contextBlock: contextBlock, rate: rate, open: open, trustFor: trustFor, TRUST_LABELS: TRUST_LABELS }
228})()

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.