Skip to content

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

Terminal window
npm install @defiant/sdk
# or
pnpm add @defiant/sdk

Quick start

import { DefiantClient } from '@defiant/sdk';
const client = new DefiantClient({
supabaseUrl: process.env.SUPABASE_URL!,
supabaseKey: process.env.SUPABASE_ANON_KEY!,
});
// Authenticate
await client.auth.signIn({
email: 'you@example.com',
password: 'your-password',
});
// Create a sprint
const sprint = await client.sprints.create({
projectId: 'proj_01hw...',
goal: 'Add user profile page with avatar and activity feed',
});
// Stream events until completion
for 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: Project

projects.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: Sprint

sprints.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 page
for await (const sprint of client.sprints.paginate({ projectId })) {
console.log(sprint.id, sprint.state);
}

Next steps