8.5 KiB
title, description
| title | description |
|---|---|
| Jetski/Cortex + Gemini Integration Guide | Come usare antigravity-awesome-skills con Jetski/Cortex evitando l’overflow di contesto con 1.332+ skill. |
Jetski/Cortex + Gemini: integrazione sicura con 1.332+ 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.
L’errore 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.mdall’avvio; - concatenare il contenuto di tutte le
SKILL.mdin un singolo system prompt; - reiniettare l’intera libreria per ogni richiesta.
Con oltre 1.332 skill, questo approccio riempie il context window prima ancora di aggiungere i messaggi dell’utente, causando l’errore di truncation.
2. Pattern raccomandato
Principi chiave:
- Manifest leggero: usare
data/skills_index.jsonper sapere quali skill esistono, senza caricare i testi completi. - Lazy loading: leggere
SKILL.mdsolo 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_ROOTprima di leggereSKILL.md.
Il flusso consigliato è:
- Bootstrap: all’avvio dell’agente leggere
data/skills_index.jsone costruire una mappaid -> meta. - Parsing dei messaggi: prima di chiamare il modello, estrarre tutti i riferimenti
@skill-iddai messaggi utente/sistema. - Risoluzione: mappare gli id trovati in oggetti
SkillMetausando la mappa di bootstrap. - Lazy load: leggere i file
SKILL.mdsolo per questi id (fino a un massimo configurabile). - 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 laSKILL.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. Pseudo‑codice di integrazione (TypeScript)
Esempio completo in:
docs/integrations/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 pre‑processing, 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.mdse 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 l’utente, impostate:
- una soglia di sicurezza (es. 70–80% del context window);
- un limite massimo di skill per turno (es. 5–10).
Strategie quando si supera la soglia:
- ridurre il numero di skill incluse (es. in base a recenza o priorità); oppure
- restituire un errore chiaro all’utente, ad esempio:
"Sono state richieste troppe skill in un singolo turno. Riduci il numero di
@skill-idnel messaggio o dividili in più passaggi."
6. Scenari di test raccomandati
- Scenario 1 – Messaggio semplice ("hi")
- Nessun
@skill-id→ nessunaSKILL.mdcaricata → il prompt rimane piccolo → nessun errore.
- Nessun
- Scenario 2 – Poche skill
- Messaggio con 1–2
@skill-id→ solo le relativeSKILL.mdvengono caricate → nessun overflow.
- Messaggio con 1–2
- Scenario 3 – Molte skill
- Messaggio con molte
@skill-id→ si attiva il limitemaxSkillsPerTurno il controllo di token → nessun overflow silenzioso.
- Messaggio con molte
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.mdper caricare solo gruppi tematici.
8. Recovery su Windows se siete gia in crash loop
Se l’host 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.
9. Riepilogo
- Non concatenate mai tutte le
SKILL.mdin un singolo prompt. - Usate
data/skills_index.jsoncome manifest leggero. - Caricate le skill on‑demand in base a
@skill-id. - Impostate limiti chiari (max skill per turno, soglia di token).
Seguendo questo pattern, Jetski/Cortex + Gemini può usare l’intera libreria di antigravity-awesome-skills in modo sicuro, scalabile e compatibile con il context window dei modelli moderni.