SDK TypeScript / JavaScript
Le SDK client officiel TypeScript / JavaScript pour Scrydon — authentification OAuth/PKCE et surface typée pour les workflows, la connaissance, le stockage, les complétions LLM et les webhooks
@scrydon/sdk est le SDK client officiel pour les applications navigateur, TanStack Start / Next.js et Node.js. Il authentifie les utilisateurs finaux via OAuth 2.0 avec PKCE et expose des modules typés pour les workflows, les complétions LLM gouvernées, la connaissance, le stockage et les webhooks, ainsi que la surface SDK data / ai / action de la plateforme.
Ce SDK est destiné aux applications first-party agissant au nom d'un utilisateur (flux OAuth). Pour une exécution serveur-à-serveur avec une clé API statique — backends, tâches cron, CI — appelez l'API de workflow directement avec x-api-key (voir Exécution).
Installation
bun add @scrydon/sdkDémarrage rapide
import { ScrydonClient } from '@scrydon/sdk'
const client = new ScrydonClient({
baseUrl: 'https://scrydon.com',
clientId: 'your-oauth-client-id',
redirectUri: 'https://your-app.com/auth/callback',
})
// 1. Start the OAuth/PKCE flow — returns the authorization URL
const authUrl = await client.auth.signIn()
window.location.assign(authUrl)
// 2. On your callback page, exchange the code for a session
const session = await client.auth.handleCallback() // reads window.location by default
// 3. Call typed APIs
const result = await client.workflows.trigger({
workflowId: 'wf_…',
inputs: { message: 'Hello, world!' },
})
console.log(result.executionId, result.status, result.outputs)Authentification — OAuth 2.0 + PKCE
Le SDK utilise le flux PKCE pour être sécurisé dans les navigateurs sans secret client. Le vérificateur est conservé dans sessionStorage (navigateur) ou en mémoire (autres environnements).
auth.signIn()
const authUrl = await client.auth.signIn()
// Redirect the user to authUrl. After consent they come back to redirectUri
// with ?code=… and ?state=… in the query string.auth.handleCallback(callbackUrl?)
// On the callback route — defaults to window.location.href
const session = await client.auth.handleCallback()
// session: { user: { id, email, name? }, accessToken, expiresAt }auth.getSession()
const session = await client.auth.getSession() // null if signed out / expiredauth.signOut()
await client.auth.signOut()auth.onAuthStateChange(cb)
const unsubscribe = client.auth.onAuthStateChange((session) => {
if (session) {
console.log('signed in as', session.user.email)
} else {
console.log('signed out')
}
})
// Later: unsubscribe()client.workflows
trigger(options) — synchrone
const result = await client.workflows.trigger({
workflowId: 'wf_abc',
inputs: { message: 'Hello' },
})
// result: { executionId, status, outputs? }POST /api/v1/workflows/{workflowId}/trigger. Idéal pour les workflows courts qui répondent en ligne.
triggerAsync(options) — déclenchement et attente
const { executionId } = await client.workflows.triggerAsync({
workflowId: 'wf_abc',
inputs: { message: 'Long task' },
})
// Poll for status when you're ready
const result = await client.workflows.getStatus(executionId)
// result: { executionId, status: 'running' | 'completed' | 'failed', outputs? }POST /api/v1/workflows/{workflowId}/trigger?async=true. À utiliser pour les workflows de longue durée.
getStatus(executionId)
const result = await client.workflows.getStatus(executionId)GET /api/v1/workflows/executions/{executionId}.
client.chat
Complétions LLM gouvernées compatibles OpenAI. Le SDK ne crée pas de session publique de chat de workflow ; envoyez l'historique dans messages et conservez-le dans votre application si nécessaire.
const stream = await client.chat.completions.create({
model: 'gpt-4o-mini',
messages: [{ role: 'user', content: 'Summarize Q3' }],
stream: true,
})
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta.content ?? '')
}Consultez le guide de migration du SDK 1.0 si vous utilisiez auparavant client.chat.stream ou useChatStream.
client.knowledge
const hits = await client.knowledge.query({
question: 'What is our refund policy?',
topK: 5,
})
// hits: Array<{ content, source, score }>
await client.knowledge.ingest({
documents: [file1, file2],
collection: 'policies',
})client.ontology
Des couches géographiques prêtes pour la carte, projetées depuis votre
ontologie — une couche par type d'objet dont les instances portent des
coordonnées (latitude/lat, longitude/lng/lon). Omettez toutes les
options pour découvrir chaque type cartographiable dans vos ontologies
lisibles ; passez objectTypes pour restreindre.
const layers = await client.ontology.queryGeo({
objectTypes: ['Aircraft', 'MilitaryBase'], // optionnel — omettre pour découvrir
ontologySlug: 'my-domain', // optionnel — omettre pour tout chercher
limit: 300, // instances max par type (1–1000)
})
// layers: Array<{ objectTypeSlug, label, features }>
// features: Array<{ id, lat, lng, label, properties }>La géo est une projection dédiée plutôt qu'une requête d'instances générique : l'extraction des coordonnées, la validation des plages et la traversée des bindings s'exécutent côté serveur, le client reçoit donc des features prêtes à rendre.
client.storage
const { url } = await client.storage.upload(file, { path: 'reports/q3.pdf' })
const directLink = await client.storage.getUrl('reports/q3.pdf')client.webhooks
Un émetteur d'événements en processus simple pour livrer les payloads webhook aux abonnés de votre application.
const off = client.webhooks.on('workflow.completed', (data) => {
console.log('workflow completed', data)
})
// Later: off()SDK plateforme — client.data, client.ai, client.action
Le client expose le ScrydonSDK typé de la plateforme :
client.data.knowledge.search(...),client.data.memex.query(...),client.data.storage.read(...),client.data.memory.add(...)— lecture / écriture de la surface de données de l'espace de travailclient.ai.llm.complete(...)— appels LLM résolus par capacitéclient.action.workflow.execute(...),client.action.email.send(...),client.action.sms.send(...),client.action.functionExecute(...)— actions côté serveur
Consultez @scrydon/sdk/types pour l'ensemble complet des types de plateforme.
Découvrir les options d'une capacité
client.integrations.capabilities.list(...) renvoie tous les fournisseurs que
votre organisation a activés pour une capacité, avec leurs modèles
sélectionnables :
const llm = await client.integrations.capabilities.list({ capability: "llm" });
llm.category; // "model" — la sélection descend jusqu'au modèle
llm.providers; // [{ providedId, extensionId, slug, name, icon?, models: [...] }]Les modèles sont déjà fusionnés : un fournisseur qui déclare un catalogue fixe et un fournisseur qui découvre ses déploiements à l'exécution ont la même forme de réponse. Le client ne doit pas créer de branche selon leur origine.
Chaque modèle contient son id natif au fournisseur, son slug de modèle et un
selectionId canonique accepté par la sélection et l'exécution Platform. La
présentation du fournisseur est représentée une seule fois par provider.slug
et l'éventuel provider.icon, au lieu d'être copiée dans chaque modèle. Un objet
metadata optionnel conserve les champs propres à la capacité, au catalogue ou
à la découverte. Pour les LLM, il peut aussi contenir contextWindow, pricing
et les capabilities effectives après combinaison des valeurs par défaut du
fournisseur et des surcharges du modèle. Ces champs connus sont typés par le
contrat exporté CapabilityListModelMetadata ; des métadonnées JSON
supplémentaires restent disponibles pour les champs propres à une capacité ou à
une intégration. Chaque clé de métadonnées reste optionnelle.
Utilisez la projection du SDK lorsqu'un sélecteur a besoin d'une liste plate et déterministe :
import { flattenCapabilityModelSelections } from "@scrydon/sdk/platform";
const selections = flattenCapabilityModelSelections(llm);
selections[0]?.selectionId; // valeur à enregistrer ou à envoyerLa category indique comment sélectionner la capacité :
| Catégorie | Signification | models |
|---|---|---|
model | sélectionner un fournisseur et un modèle (LLM, embeddings, voix, OCR, image, vidéo, modération) | présent |
general | sélectionner un fournisseur ; rien n'est sélectionnable en dessous (recherche web) | absent |
Passez applyAllowlist: false pour voir l'ensemble complet avant l'application
de la liste d'autorisation des modèles de votre organisation — utile pour créer
une interface d'administration de cette liste. Passez refresh: true pour
ignorer le cache de découverte.
Cette opération diffère de
client.integrations.capabilities.resolve(...), qui renvoie la cible unique qui
servirait la capacité à cet instant. La résolution d'un modèle conserve le
model natif au fournisseur et inclut son selectionId canonique ; les
capacités sans modèle omettent les deux champs. Utilisez resolve pour savoir
ce qui sera exécuté et list pour proposer un choix. Les consommateurs n'ont
pas à analyser ni à qualifier les identifiants de modèle de ces opérations.
Erreurs
import {
ScrydonAuthError,
ScrydonForbiddenError,
ScrydonRateLimitError,
ScrydonValidationError,
ScrydonServerError,
ScrydonError,
} from '@scrydon/sdk'
try {
await client.workflows.trigger({ workflowId: 'wf_abc' })
} catch (err) {
if (err instanceof ScrydonAuthError) {
// 401 — token expired or invalid; redirect to signIn()
} else if (err instanceof ScrydonForbiddenError) {
// 403 — user lacks permission for this workflow
} else if (err instanceof ScrydonRateLimitError) {
// 429 — err.retryAfter seconds
} else if (err instanceof ScrydonValidationError) {
// 400 — err.details has the Zod issues
} else if (err instanceof ScrydonServerError) {
// 5xx — retry with backoff
} else if (err instanceof ScrydonError) {
// Other 4xx — err.code, err.status
}
}React
@scrydon/sdk/react fournit des hooks pour les flux courants :
import { ScrydonProvider, useAuth, useWorkflow } from '@scrydon/sdk/react'
function App() {
return (
<ScrydonProvider config={{ baseUrl, clientId, redirectUri }}>
<Page />
</ScrydonProvider>
)
}
function Page() {
const { session, signIn, signOut } = useAuth()
const { trigger, result, loading, error } = useWorkflow('wf_abc')
if (!session) return <button onClick={signIn}>Sign in</button>
return (
<div>
<button onClick={() => trigger({ message: 'Hello' })} disabled={loading}>
Run workflow
</button>
{result && <pre>{JSON.stringify(result.outputs, null, 2)}</pre>}
</div>
)
}Route de callback TanStack Start / Next.js
// /auth/callback page
import { ScrydonClient } from '@scrydon/sdk'
const client = new ScrydonClient({
baseUrl: import.meta.env.VITE_SCRYDON_BASE_URL,
clientId: import.meta.env.VITE_SCRYDON_CLIENT_ID,
redirectUri: `${window.location.origin}/auth/callback`,
})
export function CallbackPage() {
useEffect(() => {
client.auth
.handleCallback()
.then(() => router.navigate({ to: '/' }))
.catch((err) => console.error('OAuth callback failed', err))
}, [])
return <p>Connexion en cours…</p>
}Backend / serveur-à-serveur
@scrydon/sdk est conçu autour d'un flux OAuth utilisateur final. Pour les processus backend qui ont besoin d'exécuter des workflows au nom de la plateforme (cron, CI, services internes), appelez l'API directement :
curl -X POST "https://scrydon.com/api/workflows/{workflowId}/execute" \
-H "x-api-key: $SCRYDON_API_KEY" \
-H "Content-Type: application/json" \
-d '{"input": "…"}'Les clés API sont émises lors du flux de déploiement (voir Exécution). Elles sont l'outil approprié pour les contextes serveur sans utilisateur final.
Prérequis
- Node.js 18+ (pour les globaux fetch + atob)
- TypeScript 5.0+ pour les types complets
- Un environnement de type navigateur pour le module React
Licence
Apache-2.0