raypilot
v1.0.1
Published
SDK oficial do RayPilot - Análise de imagens médicas DICOM com IA
Downloads
36
Maintainers
Readme
RayPilot SDK
Official SDK for integrating with the RayPilot API for AI-powered medical DICOM image analysis.
Installation
npm install raypilotQuick Start
import RayPilot from 'raypilot';
const client = new RayPilot({
apiKey: 'sk_your_key_here',
baseUrl: 'https://api.raypilot.com.br',
});DICOM Processing
Synchronous processing (waits for result)
// Node.js - reading file from disk
import { readFileSync } from 'fs';
const file = readFileSync('./exam.dcm');
const result = await client.dicom.process(file, 'exam.dcm');
console.log(result.results[0].dicomInfo?.patientName);
console.log(result.results[0].dicomInfo?.modality);// Frontend - file input
const input = document.querySelector<HTMLInputElement>('#file-input');
const file = input.files[0];
const result = await client.dicom.process(file);Asynchronous processing (queue)
// Send to queue and get a jobId
const job = await client.dicom.queue(file, {
filename: 'exam.dcm',
webhook: 'https://my-app.com/webhook/dicom', // optional
});
console.log(job.jobId); // use to check status
// Check status
const status = await client.dicom.getStatus(job.jobId);
console.log(status.status); // 'waiting' | 'active' | 'completed' | 'failed'
// Fetch result when completed
const result = await client.dicom.getResult(job.jobId);Asynchronous processing with automatic polling
// Send and automatically wait for the result
const result = await client.dicom.processAsync(file, {
filename: 'exam.dcm',
onProgress: (status) => {
console.log(`Status: ${status.status}, Progress: ${status.progress}`);
},
});
console.log(`${result.successfulFiles} files processed successfully`);AI Analysis
// Fetch AI analysis from a processed job
const analysis = await client.dicom.getAnalysis(jobId);
for (const msg of analysis.analysis.messages) {
console.log(`[${msg.role}]: ${msg.content}`);
}Streaming (large files)
// Streaming with real-time events
const result = await client.dicom.stream(zipFile, (event) => {
switch (event.type) {
case 'job_started':
console.log(`Job started: ${event.jobId}`);
break;
case 'progress':
console.log(`Stage: ${event.stage}, Files: ${event.filesFound}`);
break;
case 'file_completed':
console.log(`File ${event.filename}: ${event.success ? 'OK' : 'ERROR'}`);
break;
case 'completed':
console.log(`Done! ${event.result?.successfulFiles} files`);
break;
}
});
// For files up to 2GB
const result = await client.dicom.streamLarge(bigZipFile, (event) => {
console.log(event);
});
// Cancel streaming
await client.dicom.cancelStream(jobId);AI Chat
Chat about a processed exam
// Send a message about an exam
const response = await client.chat.send(jobId, 'What are the main findings in this exam?');
// The response includes the full history
for (const msg of response.messages) {
console.log(`[${msg.role}]: ${msg.content}`);
}Helper: quick question
// Returns only the assistant's response as a string
const answer = await client.chat.ask(jobId, 'Is there any visible fracture?');
console.log(answer);Start a chat with a new file
const response = await client.chat.create(
'Analyze this image',
[file], // File or Blob
);History and statistics
// Fetch history
const history = await client.chat.getHistory(jobId, 50);
console.log(`Total messages: ${history.totalMessages}`);
// Chat statistics
const stats = await client.chat.getStats(jobId);
console.log(`Tokens used: ${stats.totalTokensUsed}`);
// Original job context
const context = await client.chat.getContext(jobId);
// Clear history
await client.chat.clear(jobId);ZIP Upload
// Async upload
const { jobId } = await client.upload.zip(zipFile);
// Sync upload (waits for result)
const result = await client.upload.zipDirect(zipFile);
// Upload and wait with polling
const result = await client.upload.zipAndWait(zipFile, {
onProgress: (status) => console.log(status),
});API Key Verification
// Check if the API key is valid
const info = await client.keys.validate();
console.log(`Company: ${info.idempresa}, Active: ${info.isActive}`);
// Usage statistics
const stats = await client.keys.getStats('sk_your_key');
console.log(`Requests today: ${stats.requestsThisDay}`);
console.log(`Remaining (minute): ${stats.remaining.minute}`);Advanced Configuration
const client = new RayPilot({
apiKey: 'sk_your_key',
baseUrl: 'https://api.raypilot.com.br',
// Timeout per request (default: 120s)
timeout: 180_000,
// Polling interval for async jobs (default: 2s)
pollInterval: 3000,
// Maximum polling attempts (default: 300)
maxPollAttempts: 600,
// Automatic retries on 5xx errors (default: 3)
retries: 5,
});Error Handling
import {
RayPilot,
RayPilotAuthError,
RayPilotRateLimitError,
RayPilotTimeoutError,
RayPilotValidationError,
RayPilotError,
} from 'raypilot';
try {
const result = await client.dicom.process(file);
} catch (error) {
if (error instanceof RayPilotAuthError) {
console.error('Invalid or expired API key');
} else if (error instanceof RayPilotRateLimitError) {
console.error(`Rate limit! Retry in ${error.retryAfter}s`);
} else if (error instanceof RayPilotTimeoutError) {
console.error('Request timed out');
} else if (error instanceof RayPilotValidationError) {
console.error('Invalid data:', error.message);
} else if (error instanceof RayPilotError) {
console.error(`Error ${error.statusCode}: ${error.message}`);
}
}Framework Examples
Next.js (API Route)
// app/api/analyze/route.ts
import RayPilot from 'raypilot';
const client = new RayPilot({
apiKey: process.env.RAYPILOT_API_KEY!,
baseUrl: process.env.RAYPILOT_URL!,
});
export async function POST(request: Request) {
const formData = await request.formData();
const file = formData.get('file') as File;
const result = await client.dicom.processAsync(file);
return Response.json(result);
}Express
import RayPilot from 'raypilot';
import multer from 'multer';
const client = new RayPilot({
apiKey: process.env.RAYPILOT_API_KEY,
baseUrl: process.env.RAYPILOT_URL,
});
const upload = multer();
app.post('/analyze', upload.single('file'), async (req, res) => {
const result = await client.dicom.processAsync(
req.file.buffer,
{ filename: req.file.originalname },
);
res.json(result);
});React (Frontend)
import RayPilot from 'raypilot';
const client = new RayPilot({
apiKey: 'sk_client_key',
baseUrl: 'https://api.raypilot.com.br',
});
function DicomUploader() {
const [result, setResult] = useState(null);
const [loading, setLoading] = useState(false);
async function handleUpload(e: React.ChangeEvent<HTMLInputElement>) {
const file = e.target.files?.[0];
if (!file) return;
setLoading(true);
try {
const data = await client.dicom.process(file);
setResult(data);
} catch (err) {
console.error(err);
} finally {
setLoading(false);
}
}
return (
<div>
<input type="file" onChange={handleUpload} accept=".dcm" />
{loading && <p>Processing...</p>}
{result && <pre>{JSON.stringify(result, null, 2)}</pre>}
</div>
);
}Requirements
- Node.js 18+ (uses native
fetch) - Modern browsers (Chrome 42+, Firefox 39+, Safari 10.1+, Edge 14+)
License
MIT
