Documentazione
Scrivi un plugin per lo strumento assistente
Costruisci uno strumento di lettura autonomo, convalidane il manifest e gli argomenti, abilitalo deliberatamente e testa il confine del lavoratore che effettivamente ricevi.
Tradotto automaticamente dall'inglese. Vedi l'originale in inglese
Scegli il formato dell'estensione dell'assistente
Il caricatore di estensioni dell'assistente di produzione accetta una directory contenente plugin.json e una voce JavaScript in bundle. Importa il modulo in un lavoratore Bun ed espone all'assistente le funzioni dichiarate dal suo record aiTools. La funzionalità attualmente supportata è ai:tool. Questa guida crea un calcolatore di cerchi di bulloni di sola lettura che restituisce le coordinate; non inserisce la geometria in un disegno.
Esiste anche un'API ZIP del plug-in del browser in /api/plugins con manifest.json, main, autorizzazioni del browser e risorse bootstrap. Quel programma di installazione non abilita il plugin di lavoro descritto qui. IL riferimento HTTP del plugin documenti che separano il formato; Plugin spiega entrambe le superfici. Non tradurre tra loro semplicemente rinominando un manifest.
Uno strumento assistente è un codice eseguito all'interno del limite del runtime dell'applicazione. I controlli della funzionalità dell'host limitano l'accesso tramite RPC dell'host, ma il lavoratore corrente non è un sandbox del sistema operativo. Utilizza il codice di estensione la cui esecuzione è appropriata per quell'ambiente e fai in modo che il suo comportamento di lettura/scrittura dichiarato corrisponda a ciò che fa effettivamente la funzione.
Creare la directory e il record di consenso
Utilizza l'esatta directory dei dati dell'applicazione del sidecar che intendi estendere. Crea questa struttura, mantenendo l'ID della directory identico all'ID DNS inverso del manifest:
<dataDir>/plugins/
enabled.json
com.example.bolt-circle/
plugin.json
index.js Il caricatore di produzione legge Enabled.json come un array JSON di identificatori sicuri. Ignora le voci duplicate/non valide e JSON in formato errato o mancante significa che non sono abilitati plug-in. Una cartella non elencata non è caricata. Il caricatore rifiuta inoltre una mancata corrispondenza dell'ID cartella/manifest e i manifest che richiedono funzionalità non supportate.
Il caricamento avviene quando viene inizializzato il servizio plugin dell'assistente. Non configura un watcher del filesystem per il ricaricamento a caldo. Preparare e convalidare prima i file, quindi abilitare/riavviare l'istanza. Un plug-in non riuscito registra un avviso mentre gli altri plug-in e l'avvio dell'applicazione continuano; controllare tali avvisi invece di dare per scontato che una voce di file abilitato garantisca uno strumento in esecuzione.
Dichiarare un contratto strumento preciso
Questo manifest completo nomina un singolo strumento di lettura. L'ID contributo è l'identificatore locale rivolto al modello; la voce nomina la funzione esportata dal modulo. Queste stringhe possono differire, come fanno qui Bolt_circle e BoltCircle.
{
"id": "com.example.bolt-circle",
"name": "Bolt circle calculator",
"version": "1.0.0",
"apiVersion": "1",
"entry": "index.js",
"capabilities": ["ai:tool"],
"contributes": {
"aiTools": [{
"id": "bolt_circle",
"description": "Calculate equally spaced XY hole centers around the origin for a bolt circle. Returns coordinates without changing a drawing.",
"kind": "read",
"entry": "boltCircle",
"parameters": {
"type": "object",
"properties": {
"count": { "type": "integer", "minimum": 1, "maximum": 64 },
"radius": { "type": "number", "exclusiveMinimum": 0 }
},
"required": ["count", "radius"],
"additionalProperties": false
}
}]
}
} L'SDK richiede ID DNS inversi di 3–128 caratteri, una versione semantica major.minor.patch con prerelease facoltativa, versione API "1", nome/voce non vuota e funzionalità riconosciute. Gli ID strumento iniziano con una lettera minuscola e utilizzano lettere minuscole, cifre o trattini bassi fino a 40 caratteri. Le descrizioni contengono 10–2,000 caratteri. Il tipo di strumento è di lettura o scrittura; non esiste un tipo di estensione distruttiva.
Mantenere lo schema dei parametri piccolo e descrittivo. Il suo ruolo è aiutare il modello a produrre argomenti validi e consentire all'adattatore di respingere gli errori ordinari prima dell'esecuzione. Non sostituisce la convalida all'interno del codice.
Implementare il modulo autonomo
La voce esporta aiTools con la funzione di voce denominata nel manifest. Convalida nuovamente gli argomenti di runtime e restituisce un piccolo risultato compatibile con JSON. L'aritmetica delle coordinate finite e il conteggio limitato impediscono all'input non corretto di produrre un elenco illimitato o un output privo di significato.
export const aiTools = {
boltCircle: async (args) => {
if (!args || typeof args !== "object") {
return { ok: false, error: "Expected count and radius" }
}
const { count, radius } = args
if (!Number.isInteger(count) || count < 1 || count > 64) {
return { ok: false, error: "count must be an integer from 1 to 64" }
}
if (typeof radius !== "number" || !Number.isFinite(radius) || radius <= 0) {
return { ok: false, error: "radius must be a positive finite number" }
}
const holes = Array.from({ length: count }, (_, index) => {
const angle = 2 * Math.PI * index / count
return {
x: Number((radius * Math.cos(angle)).toFixed(4)),
y: Number((radius * Math.sin(angle)).toFixed(4))
}
})
return { ok: true, units: "mm", holes }
}
} Count 4 and radius 10 return centers at approximately (10,0), (0,10), (−10,0), and (0,−10), in counter-clockwise order around the origin. The result deliberately contains no database mutation or drawing identifier. A client wanting to insert holes must use a separate supported application action with its own access and permission behavior.
Raggruppare le dipendenze nella voce anziché presumere che le importazioni relative in stile nodo vengano risolte. L'host legge il testo della voce e lo importa tramite un modulo blob. Il codice di livello superiore del modulo viene eseguito durante l'importazione, quindi evita gli effetti collaterali derivanti semplicemente dal caricamento di una calcolatrice.
Convalidare il manifest ed entrambi i percorsi degli argomenti
Convalidare prima di aggiungere il plug-in a Enabled.json. Questo controllo dello sviluppo utilizza lo stesso parser manifesto dell'SDK e l'adattatore dello schema AI dell'applicazione. Posiziona lo script in un'area di lavoro con tali dipendenze, ad esempio apps/sidecar, e passa la directory assoluta del plugin come argomento.
import { join } from "node:path"
import { Effect } from "effect"
import { parseManifest } from "@cadcamfun/plugin-sdk"
import { pluginParameters } from "@cadcamfun/ai"
const directory = process.argv[2]
if (!directory) throw new Error("Pass the absolute plugin directory")
const manifest = await Effect.runPromise(parseManifest(
await Bun.file(join(directory, "plugin.json")).text()))
if (manifest.capabilities.some((capability) => capability !== "ai:tool")) {
throw new Error("This production loader accepts only ai:tool")
}
const contribution = manifest.contributes?.aiTools?.[0]
if (!contribution) throw new Error("No tool contribution")
const parameters = pluginParameters(contribution.parameters)
console.log(parameters.safeParse({ count: 4, radius: 10 }).success) // true
console.log(parameters.safeParse({ count: 0, radius: 10 }).success) // false
const module = await import(join(directory, manifest.entry))
console.log(await module.aiTools[contribution.entry]({ count: 4, radius: 10 }))
console.log(await module.aiTools[contribution.entry]({ count: 0, radius: 10 })) Le ultime due chiamate testano il comportamento a livello di funzione indipendentemente dal rifiuto dell'adattatore. L'SDK convalida la struttura del manifest, ma il caricatore di produzione aggiunge le proprie funzionalità e regole per l'ID cartella. Testare tutti e tre i limiti: dichiarazione, adattatore dell'argomento e funzione effettiva del modulo.
Abilita e scopri l'identificatore effettivo dello strumento
Dopo la convalida, abilitare l'ID nella directory dei dati dell'applicazione:
["com.example.bolt-circle"] Riavvia/reinizializza il servizio sidecar previsto e controlla i log per gli avvisi di caricamento. Quindi elenca GET /api/ai/actions. Gli strumenti dei plugin di lettura sono esposti lì così come nell'assistente incorporato; la politica può restringere il catalogo. L'identificatore dello strumento viene generato dall'ID del plugin e dall'ID dello strumento locale, normalizzato e limitato alla dimensione dell'identificatore dell'host.
Per questo manifest, l'ID derivato corrente è plugin_com_example_bolt_circle_bolt_circle. Scoprilo invece di reimplementare la regola di denominazione in ogni client. Un ID plug-in lungo può essere troncato per lasciare spazio al suffisso dello strumento. La descrizione del catalogo include il nome del plugin in modo che l'utente possa identificare la fonte.
Uno strumento di scrittura è contrassegnato per l'approvazione umana nell'assistente incorporato, indipendentemente dalla modalità di autorizzazione ordinaria. Il bridge esterno espone solo gli strumenti del plug-in di lettura e rifiuta le chiamate di estensione di scrittura anche con un token di lettura/scrittura. Sii gentile e accurato; l'applicazione non può dedurre effetti collaterali arbitrari del modulo da uno schema JSON.
Chiamare uno strumento di lettura tramite accesso esterno con ambito
Utilizza un token bridge emesso dall'applicazione per un progetto reale. Il suo portatore apre solo GET /api/ai/actions e POST /api/ai/actions/invoke. Non consente ai chiamanti di installare plug-in, modificare credenziali o enumerare progetti non correlati. Il progetto/modalità del token viene controllato dal gestore dell'azione; un token a livello di applicazione non è necessario per un client di calcolatrice autonomo.
{
"projectId": "replace-with-your-project-id",
"tool": "plugin_com_example_bolt_circle_bolt_circle",
"input": { "count": 4, "radius": 10 }
} curl --fail-with-body \
-H "Authorization: Bearer $CADCAMFUN_BRIDGE_TOKEN" \
-H "Content-Type: application/json" \
--data-binary @bridge-call.json \
"$CADCAMFUN_URL/api/ai/actions/invoke" Gli input del plugin sono l'oggetto argomento dichiarato; a differenza degli strumenti raggruppati integrati, questo plugin di lettura non richiede un discriminatore di azioni all'interno dell'input. Il bridge racchiude il valore restituito con i metadati dello strumento/azione; l'azione viene eseguita. Il livello di funzione ok=false rimane un risultato leggibile piuttosto che un successo del trasporto HTTP che dimostra un utile elenco di coordinate.
La policy bridge controlla tool.use e bridge.use. Un token mancante, scaduto, revocato o di tipo errato provoca un errore di autorizzazione. Un token associato a un altro progetto non è un modo per ampliare l'ambito di questa chiamata.
Comprendere la conversione dello schema e i limiti di capacità
L'adattatore converte lo schema JSON del contributo in zod quando rappresentabile. Se la conversione fallisce, lo schema supera i 20,000 caratteri serializzati o non descrive un oggetto, torna a uno schema di oggetti arbitrari. Questo è il motivo per cui la funzione di esempio controlla il conteggio e il raggio stesso. Il passaggio locale di un dispositivo negativo di uno schema supportato non dimostra che tutte le funzionalità dello schema rimarranno rappresentabili.
L'SDK riconosce drawing:read, drawing:write, toolpath:read, storage, ui:panel e ai:tool; disegnare scrivere implica disegnare leggere. Il caricatore dell'assistente di produzione attualmente accetta solo ai:tool. L'aggiunta di drawing:write a questo manifest fa sì che venga ignorato e non venga concesso un contesto di editor di disegno.
Il bootstrap del lavoratore generale contiene gestori di disegno/percorso utensile/interfaccia utente segnaposto. Questi gestori non sono un'integrazione della geometria di produzione. Allo stesso modo, la dichiarazione dei contributi post-processore o operativi non fa sì che l'assistente caricatore li colleghi ai registri di produzione. Scegli un'azione dell'applicazione supportata quando la funzionalità deve modificare dati CAD/CAM reali.
Progettare attorno al ciclo di vita del lavoratore implementato
L'SDK descrive un modulo con hook manifest, attivazione, pulizia facoltativa e disattivazione. L'attuale percorso AI di produzione importa la voce e richiama le funzioni aiTools esportate. I suoi gestori RPC di attivazione/disattivazione del lavoratore riconoscono i messaggi del ciclo di vita ma non richiamano gli hook del modulo esportati. Una calcolatrice può quindi utilizzare il modulo minimo mostrato qui senza dipendere dai callback di attivazione.
L'host avvia un lavoratore per plug-in abilitato, correla le risposte con gli ID RPC e tiene traccia delle chiamate in sospeso. Un'eccezione di funzione fallisce quella chiamata; test mirati su lavoratori reali mostrano che le chiamate successive possono ancora avere successo. Restituisce rifiuti strutturati per input non validi previsti e riserva gli errori generati per errori di calcolo imprevisti.
Un timeout della chiamata termina il suo lavoratore e manda immediatamente in errore il plugin. Anche gli arresti anomali del lavoratore e gli errori di pubblicazione rimuovono l'istanza in esecuzione e la contrassegnano come guasta. La cronologia degli arresti anomali ha una finestra di dieci minuti, ma il gestore corrente segnala un errore al primo arresto anomalo; non attende tre tentativi di riavvio riusciti. Correggere l'origine e ricaricare/riattivare deliberatamente invece di assumere il riavvio automatico.
Mantieni le garanzie di runtime in proporzione
Il caricatore di produzione fornisce un budget host di 10 secondi per il ciclo di vita/comando RPC ordinario. Le chiamate agli strumenti AI hanno una scadenza separata di 30 secondi. L'host limita un plug-in a 2,000 chiamate al minuto e 64 chiamate in sospeso. Passa un'impostazione di limite di risorse di 256 MB a Bun durante la creazione del lavoratore. Si tratta di controlli di runtime, non di un processo separato o di una policy di contenimento del sistema operativo.
Il bootstrap inizia con un ambiente vuoto e tenta di eliminare i processi/rete globali selezionati. L'eliminazione richiede il massimo sforzo e alcuni Bun globali rimangono raggiungibili. Il controllo della capacità è quindi significativo per le API fornite dall'host, ma non può essere presentato come un completo isolamento di JavaScript arbitrario.
Nello schema manifest sono presenti campi firma e sviluppo facoltativi. Il percorso di installazione del lavoratore corrente registra il testo della firma senza verifica crittografica. Non etichettare un editore verificato perché quel campo è presente. Una revisione autonoma del codice sorgente e una politica di installazione rimangono decisioni separate dall'accettazione dello schema.
I plug-in che si arrestano in modo anomalo tre volte in dieci minuti vengono disattivati automaticamente e una chiamata allo strumento assistente viene interrotta dopo 30 secondi. Entrambi i valori sono costanti in apps/sidecar/src/plugins/host.ts.
Aggiorna, rimuovi e diagnostica uno strumento
Per un aggiornamento, modificare e convalidare il modulo/manifest in bundle prima di riavviare il servizio di destinazione. Mantieni stabile il suo ID quando si tratta della stessa estensione e aumenta la versione per identificare cosa è stato caricato. Per interrompere il caricamento durante l'inizializzazione futura, rimuovere il relativo ID da Enabled.json e riavviare/reinizializzare. La sola modifica del file non elimina un lavoratore già in esecuzione.
Se lo strumento non è presente, controlla l'array abilitato, l'esatta uguaglianza dell'ID cartella/manifest, l'elenco delle funzionalità supportate e l'errore di decodifica del manifest nei log. NoSuchTool di solito significa che la voce non nomina una funzione aiTools esportata. Un rifiuto dell'argomento punta allo schema o alla funzione di guardia. Un timeout indica un blocco del lavoro o una promessa non mantenuta. Gli endpoint di abilitazione/configurazione ZIP del browser non gestiscono questo file di consenso dell'operatore.
La copertura mirata è arrivata apps/sidecar/test/plugins-ai-tools.test.ts per i lavoratori effettivi e ai-plugin-tools.test.ts per il caricamento della produzione, la convalida degli argomenti, l'esposizione in lettura/scrittura e il comportamento del bridge. Le fonti di implementazione sono packages/plugin-sdk/src/manifest.ts, packages/ai/src/tools/plugin-tool.ts, apps/sidecar/src/plugins/host.ts, e services/ai-plugins.ts. Utilizzare questi limiti per determinare cosa ha effettivamente dimostrato un test riuscito.
Le regole contrattuali in breve
| Articolo | Vincolo | Cosa succede se violato |
|---|---|---|
Attrezzo id | ^[a-z][a-z0-9_]{0,39}$ | La decodifica del manifest non riesce; il plugin non è caricato. |
description | 10–2,000 caratteri | La decodifica del manifest non riesce. |
kind | read o write; non esiste un tipo distruttivo | La decodifica del manifest non riesce. |
parameters | Oggetto schema JSON, al massimo 20,000 caratteri quando serializzato | Schemi sovradimensionati o non convertibili ricadono nell'accettare qualsiasi oggetto. |
| Capacità | Soltanto ai:tool nell'assistente ospite | Il plugin viene saltato con un avviso. |
| Nome della cartella | Uguale al manifesto id | Il plugin viene saltato con un avviso che nomina entrambi i valori. |
| Budget ordinario delle chiamate | 5 secondi per chiamata per impostazione predefinita | Il lavoratore viene arrestato come qualsiasi plug-in che non risponde. |
| Budget delle chiamate dello strumento Assistente | 30 s | La chiamata restituisce un risultato di errore. |
| Memoria | 256 MB di heap | L'operaio viene ucciso. |
| Valutare | 2,000 chiamate per plug-in al minuto, 64 chiamate in sospeso | Le chiamate oltre la tariffa vengono rifiutate; una coda completa fallisce plugin RPC queue is full. |
| Crash e timeout | Conteggiato su 10 minuti, limite 3 | Ogni arresto anomalo o timeout termina il lavoratore e contrassegna il plug-in in errore. |
Scrivi la descrizione del modello. Indica cosa calcola lo strumento, le sue unità e quando utilizzarlo; ad esempio, "Restituisce i centri dei fori di un cerchio di bulloni in millimetri. Da utilizzare quando l'utente richiede fori equidistanti su un diametro." Descrizioni vaghe portano a far sì che gli strumenti vengano richiamati nel momento sbagliato o non vengano richiamati affatto.
Lista di controllo pre-rilascio
- Raggruppa la voce in un unico modulo autonomo. Il lavoratore non può risolvere le importazioni dell'area di lavoro in fase di esecuzione.
- Correre
parseManifestsulla finaleplugin.jsone risolvere ogni problema segnalato. - Chiama direttamente ciascuna funzione dello strumento esportato con argomenti validi, limite e non validi e verifica che l'input non valido produca un risultato di errore leggibile anziché un'eccezione che sfugge.
- Mantieni i risultati piccoli e compatibili con JSON. L'assistente li legge e risultati di grandi dimensioni affollano il contesto.
- Scegliere
reada meno che lo strumento non cambi qualcosa. UNwritelo strumento richiede all'utente prima di ogni chiamata. - Posiziona la cartella sotto
<data dir>/plugins/<id>/, aggiungi l'ID aenabled.json, riavviare il sidecar e confermare l'ID dello strumento derivato dall'elenco degli strumenti dell'assistente. - Colpo
versionper ogni modifica che spedisci e mantieniidstabile in modo che l'ID dello strumento derivato non cambi.
Lint un manifest prima dell'installazione
import { decodeManifest, requestedCapabilities } from "@cadcamfun/plugin-sdk"
import { Effect } from "effect"
const raw = JSON.parse(await Bun.file(process.argv[2] ?? "plugin.json").text())
const manifest = await Effect.runPromise(decodeManifest(raw)) // throws a SchemaError naming the bad field
console.log(manifest.id, manifest.version, requestedCapabilities(manifest))
for (const tool of manifest.contributes?.aiTools ?? [])
console.log(`plugin_${manifest.id}_${tool.id}`, tool.kind) | Errore comune | Aggiustare |
|---|---|
"version": "1.0" | Utilizza tre numeri: 1.0.0 |
"apiVersion": 1 | È una stringa: "1" |
ID del plug-in gear o My.Plugin | DNS inverso, minuscolo: com.example.gear |
ID strumento Lookup-Thread | Lettere minuscole, cifre e trattini bassi, prima la lettera, ≤ 40 caratteri |
| Descrizione dello strumento più breve di 10 caratteri | Descrivi cosa fa e quando usarlo |
Dichiararli entrambi drawing:read e drawing:write | Consentito, ma drawing:write da solo implica già leggere |
Chiave di archiviazione che inizia con / o contenente .. | Utilizzare chiavi relative come presets/m2 |