AI Connect/Reference/Rezepte
Rezepte
Fokussierte Muster für das Einrichten von Connectors, die direkte Ausführung, schlanke Modell-Tools, Abbruch, Tracing und das Caching von Katalog-Schemas.
Diese Rezepte verwenden ausschließlich die öffentliche Oberfläche des SDK und machen den Benutzerkontext explizit. Kombinieren Sie diejenigen, die Ihre Anwendung benötigt, statt alle Aspekte in einer einzigen Route unterzubringen.
Einen serverseitigen Client wiederverwenden
// lib/vinkius.ts
import { Vinkius } from '@vinkius/connect';
export const vinkius = new Vinkius({
appId: process.env.VINKIUS_APP_ID!,
apiKey: process.env.VINKIUS_APP_KEY!,
timeoutMs: 20_000,
maxRetries: 2,
});Der Client speichert die Konfiguration der Anwendung, nicht einen aktuellen Benutzer. Leiten Sie externalId für jede eingehende Anfrage ab.
Ein Connector-Formular aus dem Katalog-Schema erstellen
import type { CredentialField, CredentialSchema } from '@vinkius/connect';
import { vinkius } from './lib/vinkius';
interface FormField {
key: string;
label: string;
required: boolean;
type: CredentialField['type'];
docsUrl?: string;
}
async function connectorForm(slug: string): Promise<FormField[]> {
const schema: CredentialSchema = await vinkius
.user('schema-only-placeholder')
.connector(slug)
.credentials.schema();
return Object.entries(schema).map(([key, field]) => ({
key,
label: field.label ?? key,
required: field.required ?? false,
type: field.type,
...(field.docs_url ? { docsUrl: field.docs_url } : {}),
}));
}Die Schema-Abfrage ist auf den Katalog beschränkt und erfordert keine echte Verbindung. Der obige Benutzer-Handle sendet keine Anfrage und dient nur dazu, die fluente Schema-Methode zu erreichen; vinkius.catalog.get(slug).credential_schema ist die direkte Low-Level-Alternative.
Connector-Credentials über eine authentifizierte Route speichern
async function saveConnector(
externalId: string,
slug: string,
values: Record<string, string>,
) {
const connector = vinkius.user(externalId).connector(slug);
await connector.connect();
const state = await connector.credentials.set(values);
return {
configured: state.configured,
status: await connector.status(),
};
}Authentifizieren und autorisieren Sie externalId, bevor Sie diese Funktion aufrufen. Gespeicherte Werte werden nicht zurückgegeben; das Ergebnis enthält Flags für die konfigurierten Schlüssel.
Den Verbindungsstatus anzeigen
const connections = await vinkius.user(externalId).connectors();
const view = connections.map((connection) => ({
slug: connection.slug,
status: connection.status,
action:
connection.status === 'ready'
? 'use'
: connection.status === 'needs_credentials'
? 'update-credentials'
: 'review-connection',
}));connectors() listet vorhandene Verbindungen auf. Sie fügt keine Katalog-Connectors hinzu, die der Benutzer noch nie verbunden hat.
Eine Aktion ohne Modell ausführen
import type { CapabilityResult } from '@vinkius/connect';
async function createIssue(
externalId: string,
input: { owner: string; repo: string; title: string },
operationId: string,
): Promise<CapabilityResult> {
const capabilities = await vinkius.user(externalId).capabilities({
include: ['github'],
});
const capability = capabilities.findCapability('github__create_issue');
if (!capability) {
throw new Error('GitHub create_issue is not available for this user');
}
return capability.execute(input, {
idempotencyKey: `create-issue:${operationId}`,
});
}Die direkte Ausführung erhält CapabilityResult und akzeptiert ExecuteOptions, anders als die Dispatch-Helfer der Adapter.
Dem Modell den kleinstmöglichen Connector-Satz geben
const issueTools = await vinkius.user(externalId).capabilities({
include: ['github'],
});
if (issueTools.length === 0) {
return { tools: [], requiresConnection: true };
}include filtert serverseitig. Verwenden Sie exclude zum lokalen Entfernen nach der Aggregation oder connector(slug).capabilities(), wenn Sie gezielt eine bestehende Verbindung möchten. Konvertieren Sie den Satz erst beim Modellaufruf:
import { toJSONSchemaTools } from '@vinkius/connect/json-schema';
const definitions = toJSONSchemaTools(issueTools);Behalten Sie issueTools für die Ausführung. Die konvertierten Definitionen enthalten nicht die benutzerbezogenen Routing-Eigenschaften.
Abbruch durch den Aufrufer hinzufügen
async function loadCapabilitiesWithBudget(externalId: string) {
const controller = new AbortController();
const timer = setTimeout(() => controller.abort('application budget exceeded'), 5_000);
try {
return await vinkius.user(externalId).capabilities({
signal: controller.signal,
});
} finally {
clearTimeout(timer);
}
}Das Signal des Aufrufers wird mit dem Timeout pro Versuch des Clients kombiniert. Übergeben Sie das Signal der eingehenden Anfrage, wenn es wichtig ist, laufende Arbeit nach dem Schließen des Clients abzubrechen. Fabrikgebundene Adapter-Ausführungen und Dispatch-Helfer akzeptieren dieses Signal nicht; rufen Sie Capability.execute() direkt auf, wenn der Abbruch die Ausführung erreichen muss.
Versuche und Anfrage-IDs nachverfolgen
const vinkius = new Vinkius({
appId: process.env.VINKIUS_APP_ID!,
apiKey: process.env.VINKIUS_APP_KEY!,
hooks: {
onRequest: ({ method, url }) => {
console.debug('Vinkius request attempt', { method, url });
},
onResponse: ({ status, requestId }) => {
console.debug('Vinkius response', { status, requestId });
},
},
});Die Hooks werden einmal pro HTTP-Versuch ausgeführt, daher können sich wiederholende Einträge automatische Wiederholungen darstellen. onRequest enthält keinen Body. onResponse erhält eine nach festen Namen redigierte Kopie des Antwort-Bodys. Halten Sie die Callbacks synchron, werfen Sie keine Fehler und vermeiden Sie unbegrenzte Arbeitslast.
Ein nicht sensibles Katalog-Schema cachen
import { ResolverCache } from '@vinkius/connect';
import type { CredentialSchema } from '@vinkius/connect';
const catalogCache = new ResolverCache(10 * 60 * 1000);
async function credentialSchema(slug: string): Promise<CredentialSchema> {
return catalogCache.resolve(`credential-schema:${slug}`, async () => {
const detail = await vinkius.catalog.get(slug);
return detail.credential_schema;
});
}ResolverCache ist eigenständig; der Client verwendet ihn nicht automatisch. Gleichzeitige Cache-Misses werden nicht zusammengeführt, abgelaufene Einträge werden beim Lesen entfernt und abgelehnte Berechnungen werden nicht gecacht. Speichern Sie niemals Credential-Werte, Bearer-Tokens oder Autorisierungsentscheidungen in diesem Cache.
