Skip to main content

React Hooks

The SDK provides 30+ React hooks built on TanStack Query v5 for data fetching, caching, and mutations.

Hook Patterns

All hooks follow consistent patterns:

// Query hooks return data + loading states
const { data, isLoading, error, refetch } = useResource();

// Hooks with actions return both queries and mutations
const { resource, actions } = useResource();
const { create, update, delete: remove } = actions;

// Actions are useMutation wrappers
await create.mutateAsync(data);

Core Hooks

useProjects

import { useProjects } from "@dgidgi/sdk";

function ProjectList() {
const {
projects, // UseQueryResult<PaginatedResponse<Project>>
actions: {
create, // UseMutationResult
delete: remove, // UseMutationResult
},
} = useProjects(workspaceId?, options?);

// Query state
const { data, isLoading, error, refetch } = projects;

// Create project
await create.mutateAsync({
name: "My Project",
description: "Description",
language: "TypeScript",
});

// Delete project
await remove.mutateAsync(projectId);
}

useProject

import { useProject } from "@dgidgi/sdk";

function ProjectDetail({ id }) {
const {
project, // UseQueryResult<Project>
actions: {
update, // UseMutationResult
},
} = useProject(id);

// Update project
await update.mutateAsync({
name: "Updated Name",
status: "active",
});
}

useProjectVersions

import { useProjectVersions, useProjectVersion } from "@dgidgi/sdk";

function VersionList({ projectId }) {
const {
versions, // UseQueryResult<ProjectVersion[]>
actions: {
create, // Create new version
release, // Release a version
setCurrent, // Set as current version
},
} = useProjectVersions(projectId);

// Create new version
const newVersion = await create.mutateAsync({
version: "1.0.0",
releaseNotes: "Initial release",
});

// Release version
await release.mutateAsync(versionId);

// Set as current
await setCurrent.mutateAsync(versionId);
}

function VersionDetail({ projectId, versionId }) {
const {
version, // UseQueryResult<ProjectVersion>
documents, // UseQueryResult<ProjectDocument[]>
actions: {
update,
linkBlueprint,
},
} = useProjectVersion(projectId, versionId);

// Link blueprint to version
await linkBlueprint.mutateAsync({
blueprintId: "blueprint-123",
});
}

useChat

import { useChat } from "@dgidgi/sdk";

function Chat() {
const {
sessions, // UseQueryResult<ChatSession[]>
actions: {
start, // Start new session
delete: remove, // Delete session
stop, // Stop running session
refinePrompt, // AI prompt refinement
complete, // Get completions
},
} = useChat({ projectId });

// Start new chat
const session = await start.mutateAsync({
projectId: "project-123",
initialMessage: "Hello!",
});

// Delete session
await remove.mutateAsync(sessionId);
}

useChatSession

import { useChatSession } from "@dgidgi/sdk";

function ChatSession({ sessionId }) {
const {
session, // UseQueryResult<ChatSession>
messages, // UseQueryResult<ChatMessage[]>
actions: {
send, // Send message
delete: remove, // Delete message
stop, // Stop generation
},
} = useChatSession(sessionId);

// Send message
await send.mutateAsync({
content: "How do I implement auth?",
role: "user",
});
}

useAgents

import { useAgents, useAgent } from "@dgidgi/sdk";

function AgentList() {
const { agents } = useAgents();

return agents.data?.data.map(agent => (
<AgentCard key={agent.id} agent={agent} />
));
}

function AgentDetail({ id }) {
const {
agent,
actions: { update, delete: remove },
} = useAgent(id);

await update.mutateAsync({
name: "Updated Agent",
config: { autonomyLevel: "high" },
});
}

useTenants

import { useTenants, useTenant, useTenantBySlug } from "@dgidgi/sdk";

// List all tenants (admin)
const { tenants } = useTenants();

// Get current tenant
const tenant = useTenant();

// Get tenant by slug
const { tenant } = useTenantBySlug("my-org");

useWorkspaces

import { useWorkspaces, useWorkspace, useCreateWorkspace } from "@dgidgi/sdk";

function Workspaces() {
const { workspaces, actions: { create } } = useWorkspaces();
const createWorkspace = useCreateWorkspace();

// Create workspace
await create.mutateAsync({
name: "New Workspace",
description: "Team workspace",
});
}

function WorkspaceDetail({ id }) {
const { workspace, actions: { update } } = useWorkspace(id);
}

useConnectors

import { useTenantConnectors, useProjectConnectors } from "@dgidgi/sdk";

// Tenant-level connectors (organization)
function ConnectorList() {
const {
connectors, // UseQueryResult<TenantConnector[]>
actions: {
create, // Connect new service
update, // Update connector
delete: remove, // Disconnect
verify, // Verify connection
},
} = useTenantConnectors();

// Connect a new service
await create.mutateAsync({
providerId: "github",
providerName: "GitHub",
category: "source_control",
authType: "oauth",
credentials: { access_token: "..." },
});

// Verify connector
await verify.mutateAsync(connectorId);

// Disconnect
await remove.mutateAsync(connectorId);
}

// Project-level connectors
function ProjectConnectors({ projectId }) {
const {
connectors, // Connectors enabled for this project
actions: {
enable, // Enable connector for project
disable, // Disable connector
update, // Update project config
},
} = useProjectConnectors(projectId);

// Enable a tenant connector for this project
await enable.mutateAsync({
tenantConnectorId: "conn_123",
config: { branch: "main" },
});
}

useConnectorProviders

import { useConnectorProviders } from "@dgidgi/sdk";

function ProviderCatalog() {
const {
providers, // All available connector providers
categories, // Provider categories
isLoading,
error,
} = useConnectorProviders();

return providers.map(provider => (
<ProviderCard
key={provider.id}
name={provider.name}
description={provider.description}
authType={provider.authType}
iconName={provider.iconName}
/>
));
}

Streaming Hooks

useStreamingChat

For real-time chat streaming:

import { useStreamingChat } from "@dgidgi/sdk";

function StreamingChat() {
const {
isStreaming,
currentText, // Accumulated response text
tasks, // Current tasks/actions
checkpoints, // Execution checkpoints
oodaPhases, // Agent OODA phases
runInfo, // Run metadata
error,
streamMessage, // Start streaming
cancelStream, // Cancel current stream
resetStream, // Reset state
} = useStreamingChat();

const handleSend = async (content: string) => {
await streamMessage({
sessionId: "session-123",
content,
projectId: "project-456",
});
};

return (
<div>
{isStreaming && <Spinner />}
<div>{currentText}</div>
<button onClick={() => handleSend("Hello!")}>Send</button>
{isStreaming && <button onClick={cancelStream}>Cancel</button>}
</div>
);
}

useStructuredStreaming

For structured event streaming:

import { useStructuredStreaming } from "@dgidgi/sdk";

function AgentRun() {
const {
isStreaming,
events, // All events received
currentPhase, // Current execution phase
taskCards, // Rendered task cards
stats, // Token/cost stats
error,
startStream,
stopStream,
} = useStructuredStreaming();

await startStream({
endpoint: `/runs/${runId}/stream`,
onEvent: (event) => {
console.log("Event:", event.type, event.data);
},
});
}

Query Options

All hooks accept React Query options:

const { projects } = useProjects(workspaceId, {
enabled: !!workspaceId, // Only fetch when workspaceId exists
staleTime: 5 * 60 * 1000, // 5 minutes
refetchOnWindowFocus: true,
refetchInterval: 30000, // Poll every 30s
onSuccess: (data) => {
console.log("Loaded projects:", data);
},
onError: (error) => {
console.error("Failed to load:", error);
},
});

Cache Invalidation

Mutations automatically invalidate relevant queries:

// When you create a project, the projects list is automatically refetched
await create.mutateAsync({ name: "New Project" });
// projects query is invalidated -> refetches automatically

// Manual invalidation
import { useQueryClient } from "@tanstack/react-query";

const queryClient = useQueryClient();
queryClient.invalidateQueries({ queryKey: ["projects"] });

Query Keys

Standard query key format:

["resource"]                    // List
["resource", id] // Single item
["resource", id, "nested"] // Nested resource
["resource", { filters }] // Filtered list

// Examples
["projects"]
["projects", "proj-123"]
["projects", "proj-123", "files"]
["chat-sessions", { projectId: "proj-123" }]

Complete Hook Reference

HookPurpose
useProjectsProject CRUD
useProjectSingle project
useProjectVersionsProject version management
useProjectVersionSingle version with documents
useChatChat sessions
useChatSessionSingle chat session
useAgentsAgent listing
useAgentSingle agent
useTenantCurrent tenant
useTenantsTenant listing
useTenantBySlugTenant by slug
useWorkspacesWorkspace listing
useWorkspaceSingle workspace
useDeploymentsDeployment listing
useDeploymentSingle deployment
useTenantConnectorsOrganization connectors
useProjectConnectorsProject-level connectors
useConnectorProvidersAvailable connector providers
useStreamingChatReal-time chat
useStructuredStreamingEvent streaming
useAIGenerateAI generation
useAIChatAI chat completion
useMarketplaceMarketplace items
useMCPServersMCP server listing
...10+ more hooks

Best Practices

  1. Use hooks, not direct resources - Hooks handle caching and invalidation
  2. Enable conditionally - Use enabled option to prevent unnecessary fetches
  3. Handle loading states - Always check isLoading before rendering data
  4. Handle errors gracefully - Use error state or error boundaries
  5. Use optimistic updates - For better UX on mutations