Files
antigravity-skills-reference/docs/integrations/jetski-cortex.md
2026-03-12 12:38:35 +01:00

8.4 KiB
Raw Blame History

title, description
title description
Jetski/Cortex + Gemini Integration Guide Come usare antigravity-awesome-skills con Jetski/Cortex evitando loverflow di contesto con 1.200+ skill.

Jetski/Cortex + Gemini: integrazione sicura con 1.200+ skill

Questa guida mostra come integrare il repository antigravity-awesome-skills con un agente basato su Jetski/Cortex + Gemini (o framework simili) senza superare il context window del modello.

Lerrore tipico visto in Jetski/Cortex è:

TrajectoryChatConverter: could not convert a single message before hitting truncation

Il problema non è nelle skill, ma nel modo in cui vengono caricate.


1. Antipattern da evitare

Non bisogna mai:

  • leggere tutte le directory skills/*/SKILL.md allavvio;
  • concatenare il contenuto di tutte le SKILL.md in un singolo system prompt;
  • reiniettare lintera libreria per ogni richiesta.

Con oltre 1.200 skill, questo approccio riempie il context window prima ancora di aggiungere i messaggi dellutente, causando lerrore di truncation.


2. Pattern raccomandato

Principi chiave:

  • Manifest leggero: usare data/skills_index.json per sapere quali skill esistono, senza caricare i testi completi.
  • Lazy loading: leggere SKILL.md solo per le skill effettivamente invocate in una conversazione (es. quando compare @skill-id).
  • Limiti espliciti: imporre un massimo di skill/tokens caricati per turno, con fallback chiari.
  • Path safety: verificare che i path del manifest restino dentro SKILLS_ROOT prima di leggere SKILL.md.

Il flusso consigliato è:

  1. Bootstrap: allavvio dellagente leggere data/skills_index.json e costruire una mappa id -> meta.
  2. Parsing dei messaggi: prima di chiamare il modello, estrarre tutti i riferimenti @skill-id dai messaggi utente/sistema.
  3. Risoluzione: mappare gli id trovati in oggetti SkillMeta usando la mappa di bootstrap.
  4. Lazy load: leggere i file SKILL.md solo per questi id (fino a un massimo configurabile).
  5. Prompt building: costruire i system messages del modello includendo solo le definizioni delle skill selezionate.

3. Struttura di skills_index.json

Il file data/skills_index.json è un array di oggetti, ad esempio:

{
  "id": "brainstorming",
  "path": "skills/brainstorming",
  "category": "planning",
  "name": "brainstorming",
  "description": "Use before any creative or constructive work.",
  "risk": "safe",
  "source": "official",
  "date_added": "2026-02-27"
}

Campi chiave:

  • id: identificatore usato nelle menzioni @id (es. @brainstorming).
  • path: directory che contiene la SKILL.md (es. skills/brainstorming/).

Per ottenere il percorso alla definizione della skill:

  • fullPath = path.join(SKILLS_ROOT, meta.path, "SKILL.md").

Nota: SKILLS_ROOT è la directory radice dove avete installato il repository (es. ~/.agent/skills).


4. Pseudocodice di integrazione (TypeScript)

Esempio completo in: examples/jetski-gemini-loader/.

4.1. Tipi di base

type SkillMeta = {
  id: string;
  path: string;
  name: string;
  description?: string;
  category?: string;
  risk?: string;
};

4.2. Bootstrap: caricare il manifest

function loadSkillIndex(indexPath: string): Map<string, SkillMeta> {
  const raw = fs.readFileSync(indexPath, "utf8");
  const arr = JSON.parse(raw) as SkillMeta[];
  const map = new Map<string, SkillMeta>();
  for (const meta of arr) {
    map.set(meta.id, meta);
  }
  return map;
}

4.3. Parsing dei messaggi per trovare @skill-id

const SKILL_ID_REGEX = /@([a-zA-Z0-9-_./]+)/g;

function resolveSkillsFromMessages(
  messages: { role: string; content: string }[],
  index: Map<string, SkillMeta>,
  maxSkills: number
): SkillMeta[] {
  const found = new Set<string>();

  for (const msg of messages) {
    let match: RegExpExecArray | null;
    while ((match = SKILL_ID_REGEX.exec(msg.content)) !== null) {
      const id = match[1];
      if (index.has(id)) {
        found.add(id);
      }
    }
  }

  const metas: SkillMeta[] = [];
  for (const id of found) {
    const meta = index.get(id);
    if (meta) metas.push(meta);
    if (metas.length >= maxSkills) break;
  }

  return metas;
}

4.4. Lazy loading dei file SKILL.md

async function loadSkillBodies(
  skillsRoot: string,
  metas: SkillMeta[]
): Promise<string[]> {
  const bodies: string[] = [];

  for (const meta of metas) {
    const fullPath = path.join(skillsRoot, meta.path, "SKILL.md");
    const text = await fs.promises.readFile(fullPath, "utf8");
    bodies.push(text);
  }

  return bodies;
}

4.5. Costruzione del prompt Jetski/Cortex

Pseudocodice per la fase di preprocessing, prima del TrajectoryChatConverter:

async function buildModelMessages(
  baseSystemMessages: { role: "system"; content: string }[],
  trajectory: { role: "user" | "assistant" | "system"; content: string }[],
  skillIndex: Map<string, SkillMeta>,
  skillsRoot: string,
  maxSkillsPerTurn: number,
  overflowBehavior: "truncate" | "error" = "truncate"
): Promise<{ role: string; content: string }[]> {
  const referencedSkills = resolveSkillsFromMessages(
    trajectory,
    skillIndex,
    Number.MAX_SAFE_INTEGER
  );
  if (
    overflowBehavior === "error" &&
    referencedSkills.length > maxSkillsPerTurn
  ) {
    throw new Error(
      `Too many skills requested in a single turn. Reduce @skill-id usage to ${maxSkillsPerTurn} or fewer.`
    );
  }

  const selectedMetas = resolveSkillsFromMessages(
    trajectory,
    skillIndex,
    maxSkillsPerTurn
  );

  const skillBodies = await loadSkillBodies(skillsRoot, selectedMetas);

  const skillMessages = skillBodies.map((body) => ({
    role: "system" as const,
    content: body,
  }));

  return [...baseSystemMessages, ...skillMessages, ...trajectory];
}

Suggerimento: aggiungete una stima dei token per troncare o riassumere i SKILL.md se il context window si avvicina al limite. Il reference loader di questo repo supporta anche un fallback esplicito: overflowBehavior: "error".


5. Gestione degli overflow di contesto

Per evitare errori difficili da capire per lutente, impostate:

  • una soglia di sicurezza (es. 7080% del context window);
  • un limite massimo di skill per turno (es. 510).

Strategie quando si supera la soglia:

  • ridurre il numero di skill incluse (es. in base a recenza o priorità); oppure
  • restituire un errore chiaro allutente, ad esempio:

"Sono state richieste troppe skill in un singolo turno. Riduci il numero di @skill-id nel messaggio o dividili in più passaggi."


6. Scenari di test raccomandati

  • Scenario 1 Messaggio semplice ("hi")
    • Nessun @skill-id → nessuna SKILL.md caricata → il prompt rimane piccolo → nessun errore.
  • Scenario 2 Poche skill
    • Messaggio con 12 @skill-id → solo le relative SKILL.md vengono caricate → nessun overflow.
  • Scenario 3 Molte skill
    • Messaggio con molte @skill-id → si attiva il limite maxSkillsPerTurn o il controllo di token → nessun overflow silenzioso.

7. Sottoinsiemi di skill e bundle

Per ulteriore controllo:

  • spostate le skill non necessarie in skills/.disabled/ per escluderle in certi ambienti;
  • usate i bundle descritti in docs/users/bundles.md per caricare solo gruppi tematici.

8. Recovery su Windows se siete gia in crash loop

Se lhost continua a riaprire la stessa trajectory corrotta dopo un errore di truncation:

  • rimuovete la skill o il pacchetto problematico;
  • cancellate Local Storage / Session Storage / IndexedDB usati da Antigravity;
  • svuotate %TEMP%;
  • riavviate con un loader lazy e limiti espliciti.

Guida completa:

Per evitare che il problema si ripresenti:

  • mantenete overflowBehavior: "error" quando preferite un fallimento esplicito;
  • continuate a validare che i path risolti restino dentro skillsRoot.

  • Non concatenate mai tutte le SKILL.md in un singolo prompt.
  • Usate data/skills_index.json come manifest leggero.
  • Caricate le skill ondemand in base a @skill-id.
  • Impostate limiti chiari (max skill per turno, soglia di token).

Seguendo questo pattern, Jetski/Cortex + Gemini può usare lintera libreria di antigravity-awesome-skills in modo sicuro, scalabile e compatibile con il context window dei modelli moderni.