@antodevs/groundtruth 0.2.1 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -41,12 +41,14 @@ Current-generation AI coding assistants (Claude Code, Antigravity, Cursor) suffe
41
41
 
42
42
  **GroundTruth** acts as a transparent middleware layer that resolves this by dynamically injecting real-time, stack-specific documentation directly into the agent's context window prior to inference.
43
43
 
44
- ### The v0.2.0 Engine: Jina Reader & Source Registry
44
+ ### The v0.2 Engine: Global Cloud Intelligence
45
+
46
+ GroundTruth v0.2 introduces a paradigm shift in context quality and scalability:
47
+ - **Global Cloud Registry**: Bypasses search engines by querying a high-performance **Cloudflare Worker** registry. It covers the top ~200 frameworks with "Golden List" manual precision and over **10,000+ npm packages** via automated background indexing.
48
+ - **Jina Reader API Integration**: Seamlessly parses dynamic, JavaScript-rendered SPAs (like Vercel AI SDK, Next.js, and Svelte docs) into clean, LLM-optimized Markdown.
49
+ - **Automated "Gentle" Indexer**: A remote bot periodically synchronizes the latest documentation URLs from the npm ecosystem directly to the cloud registry, ensuring your context is never stale.
50
+ - **Zero-Config Resilience**: Operates locally with a strictly enforced 1.5s cloud timeout. If the registry is unreachable, it silently falls back to local Readability extraction or search.
45
51
 
46
- GroundTruth v0.2.0 introduces a massive upgrade to content quality:
47
- - **Jina Reader API Integration**: Parses dynamic, JavaScript-rendered SPAs (like Vercel AI SDK, Next.js, and Svelte docs) into clean, LLM-optimized Markdown.
48
- - **Smart Source Registry**: Automatically bypasses search engines for the top 20+ frameworks (React, Svelte, Vue, Astro, etc.) and fetches their official documentation directly.
49
- - **Readability Fallback**: Ensures reliable extraction even if the primary engine fails.
50
52
 
51
53
  ---
52
54
 
package/package.json CHANGED
@@ -1,7 +1,10 @@
1
1
  {
2
2
  "name": "@antodevs/groundtruth",
3
- "version": "0.2.1",
3
+ "version": "0.2.5",
4
4
  "description": "Lightweight Node.js proxy to intercept API requests from coding agents and inject fresh web context",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
5
8
  "type": "module",
6
9
  "license": "MIT",
7
10
  "author": "Anto",
package/src/registry.js CHANGED
@@ -1,62 +1,55 @@
1
1
  /**
2
2
  * @module registry
3
- * @description Mappa hardcodata dipendenza URL docs ufficiale per bypass DDG su framework noti.
3
+ * @description Interroga il Cloudflare Worker (Remote Registry) per risolvere URL docs ufficiali.
4
4
  */
5
+ import fetch from 'node-fetch';
5
6
 
6
- // ─── Docs URL Registry ──────────────────────────────
7
-
8
- const DOCS_REGISTRY = {
9
- 'svelte': 'https://svelte.dev/docs/svelte/overview',
10
- 'sveltekit': 'https://svelte.dev/docs/kit/introduction',
11
- 'react': 'https://react.dev/reference/react',
12
- 'react-dom': 'https://react.dev/reference/react-dom',
13
- 'next': 'https://nextjs.org/docs',
14
- 'nextjs': 'https://nextjs.org/docs',
15
- 'vue': 'https://vuejs.org/api/',
16
- 'nuxt': 'https://nuxt.com/docs/api',
17
- 'angular': 'https://angular.dev/overview',
18
- 'astro': 'https://docs.astro.build/en/reference/configuration-reference/',
19
- 'tailwindcss': 'https://tailwindcss.com/docs',
20
- 'typescript': 'https://www.typescriptlang.org/docs/',
21
- 'express': 'https://expressjs.com/en/5x/api.html',
22
- 'fastify': 'https://fastify.dev/docs/latest/',
23
- 'hono': 'https://hono.dev/docs/',
24
- 'solid-js': 'https://docs.solidjs.com/',
25
- 'qwik': 'https://qwik.dev/docs/',
26
- 'remix': 'https://remix.run/docs/en/main',
27
- 'prisma': 'https://www.prisma.io/docs',
28
- 'drizzle-orm': 'https://orm.drizzle.team/docs/overview',
29
- 'three': 'https://threejs.org/docs/',
30
- 'zod': 'https://zod.dev/',
31
- 'trpc': 'https://trpc.io/docs',
32
- 'tanstack-query': 'https://tanstack.com/query/latest/docs/overview',
33
- };
7
+ const REGISTRY_API_URL = 'https://groundtruth-registry.antony-flex01.workers.dev/lookup';
8
+
9
+ // Cache in memoria per evitare query multiple allo stesso endpoint durante lo stesso run del watcher
10
+ const lookupCache = new Map();
34
11
 
35
12
  /**
36
- * @description Normalizza nome dipendenza e cerca URL docs nel registry.
13
+ * @description Interroga asincronamente l'API cloudflare per cercare URL docs nel registry remoto
37
14
  * @param {string} depName - Nome dipendenza da package.json (es. "svelte 5.51" o "@sveltejs/kit")
38
- * @returns {string|null} URL docs diretto o null se non trovato
15
+ * @returns {Promise<string|null>} URL docs diretto o null se non trovato/errore (fallback DDG cerniera)
39
16
  */
40
- export function lookupRegistryUrl(depName) {
41
- // Prende solo il nome senza versione ("svelte 5.51" → "svelte")
42
- const name = depName.split(' ')[0].toLowerCase();
43
-
44
- // Match diretto
45
- if (DOCS_REGISTRY[name]) return DOCS_REGISTRY[name];
46
-
47
- // Strip @scope/ prefix ("@sveltejs/kit" → "kit", ma usiamo mapping speciali)
48
- if (name === '@sveltejs/kit') return DOCS_REGISTRY['sveltekit'];
49
- if (name === 'next' || name === '@next/core') return DOCS_REGISTRY['next'];
50
-
51
- // Generic scope strip
52
- const stripped = name.startsWith('@') ? name.split('/')[1] : name;
53
- if (DOCS_REGISTRY[stripped]) return DOCS_REGISTRY[stripped];
54
-
55
- // Strip -js suffix ("solid-js" → "solid")
56
- const noJs = stripped.replace(/-js$/, '');
57
- if (noJs !== stripped && DOCS_REGISTRY[noJs]) return DOCS_REGISTRY[noJs];
58
-
59
- return null;
17
+ export async function lookupRegistryUrl(depName) {
18
+ if (!depName) return null;
19
+
20
+ // Normalizzazione preventiva
21
+ const name = depName.split(' ')[0].toLowerCase().trim();
22
+
23
+ // Check hit in memoria (ritorna subito)
24
+ if (lookupCache.has(name)) {
25
+ return lookupCache.get(name);
26
+ }
27
+
28
+ try {
29
+ // Fetch asincrono con timeout stretto per evitare latenze di fallback
30
+ const res = await fetch(`${REGISTRY_API_URL}?pkg=${encodeURIComponent(name)}`, {
31
+ signal: AbortSignal.timeout(1500), // Max 1.5s aspetta il Cloudflare worker
32
+ headers: {
33
+ 'Accept': 'application/json'
34
+ }
35
+ });
36
+
37
+ if (res.ok) {
38
+ const data = await res.json();
39
+ if (data && data.found && data.url) {
40
+ lookupCache.set(name, data.url); // Cache hit success
41
+ return data.url;
42
+ }
43
+ }
44
+
45
+ // Se l'API restituisce 404/not found
46
+ lookupCache.set(name, null); // Cache negative (così non rifacciamo network)
47
+ return null;
48
+
49
+ } catch (err) {
50
+ // Failover silente! (timeout o worker rotto). Se Cloudflare fallisce,
51
+ // noi non diamo errore all'utente ma facciamo DDG search fallback locale naturale.
52
+ lookupCache.set(name, null);
53
+ return null;
54
+ }
60
55
  }
61
-
62
- export { DOCS_REGISTRY };
package/src/search.js CHANGED
@@ -96,7 +96,7 @@ export async function registryFetch(deps, opts = {}) {
96
96
  const coveredDeps = new Set();
97
97
 
98
98
  for (const dep of deps) {
99
- const docUrl = lookupRegistryUrl(dep);
99
+ const docUrl = await lookupRegistryUrl(dep);
100
100
  if (!docUrl) continue;
101
101
 
102
102
  const depName = dep.split(' ')[0];