Scrydon

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/sdk

Dé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 / expired

auth.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 travail
  • client.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 à envoyer

La category indique comment sélectionner la capacité :

CatégorieSignificationmodels
modelsélectionner un fournisseur et un modèle (LLM, embeddings, voix, OCR, image, vidéo, modération)présent
generalsé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

Sur cette page

Sur cette page