TypeScript SDK
The @defiant/sdk package provides a typed TypeScript client for the Defiant REST API. It wraps all endpoints with async methods, handles authentication, and provides a streaming interface for real-time sprint events.
Installation
npm install @defiant/sdk# orpnpm add @defiant/sdkQuick start
import { DefiantClient } from '@defiant/sdk';
const client = new DefiantClient({ supabaseUrl: process.env.SUPABASE_URL!, supabaseKey: process.env.SUPABASE_ANON_KEY!,});
// Authenticateawait client.auth.signIn({ email: 'you@example.com', password: 'your-password',});
// Create a sprintconst sprint = await client.sprints.create({ projectId: 'proj_01hw...', goal: 'Add user profile page with avatar and activity feed',});
// Stream events until completionfor await (const event of client.sprints.stream(sprint.id)) { console.log(event.type, event.state); if (event.state === 'COMPLETE' || event.state === 'FAILED') break;}DefiantClient
Constructor
const client = new DefiantClient({ supabaseUrl: string; // your Supabase project URL supabaseKey: string; // anon key for user auth, service key for server-side baseUrl?: string; // override the Edge Function base URL timeout?: number; // request timeout in ms (default: 30000) retries?: number; // number of retries on 5xx (default: 3)});client.auth
auth.signIn
const session = await client.auth.signIn({ email: string; password: string;});// Returns: { user: User; session: Session }auth.signInWithToken
For server-side use with a JWT you already have:
client.auth.signInWithToken(jwt: string): void;auth.signOut
await client.auth.signOut();client.projects
projects.list
const { data } = await client.projects.list();// data: Project[]projects.create
const project = await client.projects.create({ name: string; repo: string; // 'owner/name' vertical: Vertical; // 'solo-founder' | 'b2b-saas' | 'marketplace' | 'fintech' | 'healthcare' | 'pe-portfolio' branch?: string; // default: 'main' deployUrl?: string;});// Returns: Projectprojects.get
const project = await client.projects.get(projectId: string);projects.update
const updated = await client.projects.update(projectId, { vertical?: Vertical; deployUrl?: string;});projects.delete
await client.projects.delete(projectId: string);client.sprints
sprints.create
const sprint = await client.sprints.create({ projectId: string; goal: string; priority?: 'low' | 'normal' | 'high'; // default: 'normal' tokenBudget?: number; // default: 200000});// Returns: Sprintsprints.get
const sprint = await client.sprints.get(sprintId: string);// Returns: SprintDetail (includes technicalPlan, agents, prs)sprints.list
const { data, meta } = await client.sprints.list({ projectId?: string; state?: 'active' | 'complete' | 'failed' | 'blocked'; limit?: number; offset?: number;});sprints.cancel
await client.sprints.cancel(sprintId: string);sprints.retry
await client.sprints.retry(sprintId: string, { fromState?: SprintState;});sprints.stream
Returns an async iterator of SprintEvent objects via Server-Sent Events:
for await (const event of client.sprints.stream(sprintId)) { switch (event.type) { case 'state.transition': console.log(`${event.from} → ${event.to}`); break; case 'agent.dispatched': console.log(`Agent dispatched: ${event.agent}`); break; case 'agent.completed': console.log(`Agent completed: ${event.agent}`); break; case 'pr.opened': console.log(`PR opened: ${event.prUrl}`); break; case 'mandate.violated': console.error(`Mandate violation: ${event.mandateId} — ${event.message}`); break; }
// Break on terminal states if (['COMPLETE', 'FAILED', 'CANCELLED'].includes(event.state)) break;}sprints.waitForComplete
Convenience method that wraps stream and resolves when the sprint reaches a terminal state:
const result = await client.sprints.waitForComplete(sprintId, { timeout?: number; // ms; default: 7200000 (2 hours) onEvent?: (event: SprintEvent) => void;});
if (result.state === 'COMPLETE') { console.log('Sprint complete!', result.tokensUsed);} else { console.error('Sprint failed:', result.failureReason);}client.events
events.list
const { data } = await client.events.list({ sprintId?: string; projectId?: string; type?: EventType; agentId?: string; since?: string; // ISO 8601 before?: string; // ISO 8601 limit?: number;});client.inbox
inbox.list
const { data } = await client.inbox.list({ resolved?: boolean; // default: false priority?: 'critical' | 'high' | 'low';});inbox.resolve
await client.inbox.resolve(inboxItemId, { response: string;});client.mandates
mandates.list
const { data } = await client.mandates.list({ projectId?: string; category?: 'security' | 'quality' | 'compliance' | 'process' | 'architecture';});mandates.check
const result = await client.mandates.check({ projectId: string; mandateId?: string; files: Record<string, string>; // { 'src/foo.ts': '<contents>' }});
// result.passed: boolean// result.violations: MandateViolation[]Type definitions
type Vertical = | 'solo-founder' | 'b2b-saas' | 'marketplace' | 'fintech' | 'healthcare' | 'pe-portfolio';
type SprintState = | 'INTAKE' | 'THINK' | 'PLAN' | 'BUILD' | 'SHIP' | 'COMPLETE' | 'BLOCKED' | 'FAILED' | 'CANCELLED';
interface Project { id: string; name: string; repo: string; vertical: Vertical; branch: string; deployUrl: string | null; createdAt: string; updatedAt: string;}
interface Sprint { id: string; projectId: string; goal: string; state: SprintState; priority: 'low' | 'normal' | 'high'; tokenBudget: number; tokensUsed: number; agents: AgentId[]; prs: PR[]; createdAt: string; updatedAt: string;}
interface SprintEvent { id: string; type: EventType; sprintId: string; state: SprintState; agent?: AgentId; from?: SprintState; to?: SprintState; prUrl?: string; mandateId?: string; message?: string; createdAt: string;}Error handling
All SDK methods throw DefiantError on failure:
import { DefiantError } from '@defiant/sdk';
try { const sprint = await client.sprints.create({ projectId, goal });} catch (err) { if (err instanceof DefiantError) { console.error(err.code); // 'CONDUCTOR_OFFLINE' | 'BUDGET_EXHAUSTED' | ... console.error(err.message); console.error(err.status); // HTTP status code }}Pagination helper
// Iterate all sprints for a project, page by pagefor await (const sprint of client.sprints.paginate({ projectId })) { console.log(sprint.id, sprint.state);}Next steps
- REST API Reference for the raw HTTP interface
- MCP Server to call Defiant from Claude directly