@kontext.dev/kontext-sdk
v0.3.5
Published
Unified SDK for AI-powered context and personalization
Downloads
93
Maintainers
Readme
Kontext SDK
Kontext’s TypeScript SDK helps you ship personalization fast: one install gives you the server client, browser wrapper, token utilities, and polished React components. This guide walks through the new user-ID-first authentication flow.
Quick start (React + API route)
Install the package
pnpm add @kontext.dev/kontext-sdkExpose a user-token minting endpoint — your backend exchanges a developer API key + user ID for a short-lived JWT.
// apps/api/kontext/user-token/route.ts import { createUserTokenHandler } from '@kontext.dev/kontext-sdk/server'; export const POST = createUserTokenHandler({ apiKey: process.env.KONTEXT_API_KEY!, kontextApiUrl: process.env.KONTEXT_API_URL, });Wrap your app with
<KontextApp>and pass the current user ID// app/layout.tsx (Next.js example) import React from 'react'; import { KontextApp, useKontext } from '@kontext.dev/kontext-sdk/react'; export default function RootLayout({ children }: { children: React.ReactNode }) { const user = useAuth(); // ← replace with your auth/session hook return ( <html> <body> <KontextApp userId={user?.id ?? null} userTokenEndpoint="/api/kontext/user-token"> <Main /> {children} </KontextApp> </body> </html> ); } function Main() { const { isGmailConnected, connectGmail } = useKontext(); return isGmailConnected ? <Chat /> : <button onClick={connectGmail}>Connect Gmail</button>; }
KontextApp never generates user IDs for you; supply the one from your auth system. The SDK stores the user ID locally, mints tokens when needed, and exposes Gmail connection state so you can show reconnect flows or purge confidently.
Auth flow overview
| Flow | Who holds credentials? | What the SDK sends | Typical use |
| -------------------------------------------- | -------------------------------- | ----------------------------------------------- | ----------------------------------------------------------- |
| Trusted server (API route, worker, cron) | Developer API key | Authorization: Bearer <API key> + X-As-User | Your backend calling Kontext (/auth/user_token, /vault) |
| Browser / untrusted client | Per-user JWT (minted by backend) | Authorization: Bearer <user token> | React app via <KontextApp> and hooks |
Even in the browser flow, the API key never reaches end users. The frontend asks your backend for a scoped JWT, the SDK refreshes it automatically, and Gmail OAuth calls are proxied with either that JWT or your API key (kept server-side).
SDK building blocks
| Module | Import path | Use when… |
| --------------------------------------------------------------------------------------- | ------------------------------------- | ------------------------------------------------------------------------- |
| Core client (Kontext, VaultClient, ProfileClient) | @kontext.dev/kontext-sdk | Server code with the API key or browser code that already has a user JWT. |
| React wrapper + hooks (KontextApp, useKontext, useKontextProfile, realtime hooks) | @kontext.dev/kontext-sdk/react | Browser apps that need token issuance, Gmail state, and profile caching. |
| Server helper (createUserTokenHandler) | @kontext.dev/kontext-sdk/server | Quickly create your /auth/user_token exchange endpoint. |
| UI components (KontextConnectButton, KontextStatus, KontextModal, …) | @kontext.dev/kontext-sdk/components | Ready-made Gmail connect/disconnect UX. |
Direct server calls (API key)
Use this pattern when a trusted backend talks to the Kontext API directly—e.g., benchmarking, vault ingestion, or one-off maintenance tasks. Gmail/OAuth flows still go through the React/browser flow because the user must grant consent client-side.
import { Kontext } from '@kontext.dev/kontext-sdk';
const apiKey = process.env.KONTEXT_API_KEY;
const userId = ctx.auth.user.id;
if (!apiKey || !userId) {
throw new Error('Both apiKey and userId are required');
}
const kontext = new Kontext({
apiKey,
userId,
apiUrl: process.env.KONTEXT_API_URL ?? 'https://api.kontext.dev',
});
const profile = await kontext.profile.getProfile({ userId, task: 'chat' });
const answer = await kontext.vault.query({ userId, query: 'recent news', includeAnswer: true });
await kontext.users.purge({ userId });The client mints per-user JWTs under the hood before calling /profile/*, /vault/*, or /users/* so you never handle them manually on the server.
React reference
const {
userId,
connectionStatus, // 'initializing' | 'ready' | 'missing-user' | 'token-error'
gmailStatus, // 'unknown' | 'connected' | 'disconnected' | 'error'
isGmailConnected,
isUserReady,
connectGmail,
disconnect,
ensureUserToken,
} = useKontext();isUserReadyturnstrueonce a user ID is supplied and a token is minted.gmailStatushelps you show reconnect/error states distinct from generic loading.ensureUserToken(userId?, { forceRefresh })gives you a fresh JWT when you need to call your own backend on behalf of the user.
useKontextProfile() still exposes { systemPrompt, lastUpdated, isStale, refresh } for lightweight profile displays.
First-run checklist
- Supply a stable
userIdfrom your auth/session layer (Kontext never generates one). - Mint a user token via
/auth/user_token, then mount<KontextApp userId=... />. - When
gmailStatus === 'disconnected', prompt the user to runconnectGmail(); only defer profile fetches until Gmail consent completes (vault endpoints remain available). - Defer personalization UI until
gmailStatus === 'connected'andconnectionStatus === 'ready'.
Gmail-aware UI helpers
- KontextConnectButton automatically switches between “Connect” and “Reconnect” based on
isGmailConnectedand disables itself untilisUserReady. - KontextStatus shows loading vs disconnected vs connected states using the new status fields.
- KontextModal packages the complete flow (connect, reconnect, disconnect, profile freshness) in a single component.
API quick reference
await kontext.profile.getProfile({ userId, task: 'chat', userQuery, privacyLevel: 'moderate' });
await kontext.profile.listFacts({ userId, limit: 20 });
await kontext.profile.deleteFacts({ userId, factIds: ['fact_1', 'fact_2'] });
await kontext.vault.upload({ userId, file });
await kontext.vault.getFileStatus({ userId, fileId });
await kontext.vault.listFiles({ userId });
await kontext.vault.query({ userId, query, includeAnswer: true });
await kontext.vault.deleteFile({ userId, fileId });
await kontext.vault.clearVault({ userId });KontextError surfaces issues like UNAUTHORIZED_USER (no Gmail consent) or INVALID_USER_ID (malformed input) so you can prompt the right action.
Troubleshooting
- 401 → The user hasn’t connected Gmail yet. Call
connectGmail(). - 403 → Check that your frontend origin is registered in the developer dashboard.
- Token failures →
connectionStatusbecomes'token-error'. For consent issues, onlygmailStatuswill flip to'disconnected'. - Rate limits → 60
/auth/user_tokencalls/min per developer, 30 vault writes & 120 reads/min. - Keep
KONTEXT_API_KEYserver-side—only per-user JWTs ever reach the browser.
Need a deeper example? Check the starter repo: https://github.com/co-browser/assistant-ui-kontext-starter or email [email protected].
