'use client'; import React, { useState } from 'react'; // --------------------------------------------------------------------------- // Types // --------------------------------------------------------------------------- type Sdk = 'nodejs' | 'python' | 'go' | 'java'; interface WizardState { step: 1 | 2 | 3 | 4; agentName: string; agentId: string | null; clientId: string | null; clientSecret: string | null; selectedSdk: Sdk; loading: boolean; error: string | null; } interface AgentCreateResponse { agentId: string; } interface CredentialsResponse { clientId: string; clientSecret: string; } // --------------------------------------------------------------------------- // SDK code snippets // --------------------------------------------------------------------------- function buildSnippet( sdk: Sdk, apiUrl: string, clientId: string, clientSecret: string ): string { switch (sdk) { case 'nodejs': return `import { AgentIdPClient } from '@sentryagent/idp-sdk'; const client = new AgentIdPClient({ apiUrl: '${apiUrl}', clientId: '${clientId}', clientSecret: '${clientSecret}', }); const { accessToken } = await client.tokens.issue(); console.log('Access token:', accessToken);`; case 'python': return `from sentryagent_idp import AgentIdPClient client = AgentIdPClient( api_url="${apiUrl}", client_id="${clientId}", client_secret="${clientSecret}", ) token_response = client.tokens.issue() print("Access token:", token_response.access_token)`; case 'go': return `import idp "github.com/sentryagent/idp-sdk-go" client := idp.NewClient(idp.Config{ APIURL: "${apiUrl}", ClientID: "${clientId}", ClientSecret: "${clientSecret}", }) token, err := client.Tokens.Issue(ctx) if err != nil { panic(err) } fmt.Println("Access token:", token.AccessToken)`; case 'java': return `AgentIdPClient client = AgentIdPClient.builder() .apiUrl("${apiUrl}") .clientId("${clientId}") .clientSecret("${clientSecret}") .build(); TokenResponse token = client.tokens().issue(); System.out.println("Access token: " + token.getAccessToken());`; default: return ''; } } // --------------------------------------------------------------------------- // Shared UI helpers // --------------------------------------------------------------------------- function StepIndicator({ current, total, }: { current: number; total: number; }): React.ReactElement { return (
{Array.from({ length: total }, (_, i) => i + 1).map((n) => (
{n < current ? '✓' : n}
{n < total && (
)} ))}
); } function CopyButton({ text }: { text: string }): React.ReactElement { const [copied, setCopied] = useState(false); const handleCopy = async (): Promise => { await navigator.clipboard.writeText(text); setCopied(true); setTimeout(() => setCopied(false), 2000); }; return ( ); } function ErrorAlert({ message }: { message: string }): React.ReactElement { return (
{message}
); } // --------------------------------------------------------------------------- // Step components // --------------------------------------------------------------------------- function Step1AccountSetup({ onNext, }: { onNext: () => void; }): React.ReactElement { return (

Step 1: Account Setup

Before registering your first agent, make sure you have the AgentIdP server running.

    {[ { n: 1, title: 'Clone the repository', code: 'git clone https://github.com/sentryagent/sentryagent-idp.git', }, { n: 2, title: 'Copy environment variables', code: 'cp .env.example .env', }, { n: 3, title: 'Start the server', code: 'docker compose up -d && npm run db:migrate', }, { n: 4, title: 'Verify the server is healthy', code: 'curl http://localhost:3000/health', }, ].map(({ n, title, code }) => (
  1. {n}

    {title}

    {code}
  2. ))}
); } function Step2RegisterAgent({ agentName, onAgentNameChange, agentId, loading, error, onRegister, onNext, }: { agentName: string; onAgentNameChange: (v: string) => void; agentId: string | null; loading: boolean; error: string | null; onRegister: () => void; onNext: () => void; }): React.ReactElement { return (

Step 2: Register Your Agent

Give your agent a name and register it with AgentIdP. You will receive a unique Agent ID.

{error && } {agentId ? (

Agent registered successfully!

Agent ID:{' '} {agentId}

) : (
onAgentNameChange(e.target.value)} placeholder="e.g. my-summarisation-agent" className="flex-1 rounded-lg border border-slate-300 px-4 py-2.5 text-sm focus:border-brand-500 focus:outline-none focus:ring-2 focus:ring-brand-200" />
)} {agentId && ( )}
); } function Step3GenerateCredentials({ agentId, clientId, clientSecret, loading, error, onGenerate, onNext, }: { agentId: string; clientId: string | null; clientSecret: string | null; loading: boolean; error: string | null; onGenerate: () => void; onNext: () => void; }): React.ReactElement { return (

Step 3: Generate Credentials

Generate OAuth 2.0 client credentials for agent{' '} {agentId} . Store your client secret securely — it will not be shown again.

{error && } {clientId && clientSecret ? (

Credentials generated. Store these securely!

Client ID

{clientId}

Client Secret

{clientSecret}
) : ( )} {clientId && clientSecret && ( )}
); } const SDK_OPTIONS: { id: Sdk; label: string; description: string }[] = [ { id: 'nodejs', label: 'Node.js / TypeScript', description: 'npm install @sentryagent/idp-sdk', }, { id: 'python', label: 'Python', description: 'pip install sentryagent-idp', }, { id: 'go', label: 'Go', description: 'go get github.com/sentryagent/idp-sdk-go', }, { id: 'java', label: 'Java', description: 'Maven / Gradle — ai.sentryagent:idp-sdk:1.0.0', }, ]; function Step4SdkSelection({ selectedSdk, onSdkChange, clientId, clientSecret, apiUrl, }: { selectedSdk: Sdk; onSdkChange: (sdk: Sdk) => void; clientId: string; clientSecret: string; apiUrl: string; }): React.ReactElement { const snippet = buildSnippet(selectedSdk, apiUrl, clientId, clientSecret); return (

Step 4: Choose Your SDK

Select your language and copy the ready-to-run code snippet below. Your credentials are pre-filled.

{SDK_OPTIONS.map(({ id, label, description }) => ( ))}

Ready-to-run code

          {snippet}
        

You are all set!

Your agent is registered and you have credentials. Start making authenticated API calls using the snippet above.

); } // --------------------------------------------------------------------------- // Main wizard component // --------------------------------------------------------------------------- interface GetStartedWizardProps { apiUrl: string; } export function GetStartedWizard({ apiUrl, }: GetStartedWizardProps): React.ReactElement { const [state, setState] = useState({ step: 1, agentName: '', agentId: null, clientId: null, clientSecret: null, selectedSdk: 'nodejs', loading: false, error: null, }); const goToStep = (step: WizardState['step']): void => { setState((prev) => ({ ...prev, step, error: null })); }; const handleAgentNameChange = (value: string): void => { setState((prev) => ({ ...prev, agentName: value })); }; const handleSdkChange = (sdk: Sdk): void => { setState((prev) => ({ ...prev, selectedSdk: sdk })); }; const handleRegisterAgent = async (): Promise => { setState((prev) => ({ ...prev, loading: true, error: null })); try { const response = await fetch(`${apiUrl}/agents`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name: state.agentName.trim() }), }); if (!response.ok) { const body = (await response.json()) as { message?: string }; throw new Error(body.message ?? `HTTP ${response.status}`); } const data = (await response.json()) as AgentCreateResponse; setState((prev) => ({ ...prev, agentId: data.agentId, loading: false, error: null, })); } catch (err) { setState((prev) => ({ ...prev, loading: false, error: err instanceof Error ? err.message : 'Failed to register agent', })); } }; const handleGenerateCredentials = async (): Promise => { if (!state.agentId) return; setState((prev) => ({ ...prev, loading: true, error: null })); try { const response = await fetch( `${apiUrl}/agents/${state.agentId}/credentials`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, } ); if (!response.ok) { const body = (await response.json()) as { message?: string }; throw new Error(body.message ?? `HTTP ${response.status}`); } const data = (await response.json()) as CredentialsResponse; setState((prev) => ({ ...prev, clientId: data.clientId, clientSecret: data.clientSecret, loading: false, error: null, })); } catch (err) { setState((prev) => ({ ...prev, loading: false, error: err instanceof Error ? err.message : 'Failed to generate credentials', })); } }; const stepLabels = [ 'Account Setup', 'Register Agent', 'Generate Credentials', 'Choose SDK', ]; return (
{/* Step label row */}
{stepLabels.map((label, i) => ( {label} ))}
{state.step === 1 && ( goToStep(2)} /> )} {state.step === 2 && ( void handleRegisterAgent()} onNext={() => goToStep(3)} /> )} {state.step === 3 && state.agentId && ( void handleGenerateCredentials()} onNext={() => goToStep(4)} /> )} {state.step === 4 && state.clientId && state.clientSecret && ( )}
); }