apiingest-lite / index.html
aegisceo's picture
Add 2 files
57f951b verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>API Ingestion Tool for LLMs</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
.animate-pulse-slow {
animation: pulse 2.5s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
.scrollbar-hide::-webkit-scrollbar {
display: none;
}
.json-viewer {
font-family: 'Courier New', monospace;
font-size: 0.9rem;
background-color: #111827;
border-radius: 0.5rem;
}
body {
background-color: #181818;
color: #e5e7eb;
}
.bg-white {
background-color: #1f2937;
}
.text-gray-800 {
color: #e5e7eb;
}
.text-gray-700 {
color: #d1d5db;
}
.text-gray-600 {
color: #9ca3af;
}
.border-gray-200, .border-gray-300 {
border-color: #374151;
}
.bg-gray-100 {
background-color: #111827;
}
.bg-gray-50 {
background-color: #1f2937;
}
.bg-blue-50 {
background-color: #1e3a8a;
}
.bg-indigo-50 {
background-color: #3730a3;
}
.bg-purple-50 {
background-color: #5b21b6;
}
.bg-pink-50 {
background-color: #9d174d;
}
.bg-amber-50 {
background-color: #78350f;
}
.bg-yellow-100 {
background-color: #854d0e;
}
.bg-indigo-100 {
background-color: #3730a3;
}
.bg-indigo-50 {
background-color: #312e81;
}
.text-blue-700, .text-purple-700, .text-indigo-700, .text-pink-700, .text-yellow-800 {
color: #e5e7eb;
}
</style>
</head>
<body class="min-h-screen">
<div class="container mx-auto px-4 py-8 max-w-5xl">
<!-- Header -->
<header class="mb-8 text-center">
<h1 class="text-3xl font-bold">
<span class="text-blue-400">API</span> Ingestion Tool <span class="text-gray-400">for LLMs</span>
</h1>
<p class="text-gray-400 mt-2">Automate API documentation ingestion for your large language models</p>
</header>
<!-- Main Content -->
<div class="grid grid-cols-1 md:grid-cols-5 gap-6">
<!-- Left Panel - API Configuration -->
<div class="md:col-span-3 space-y-6">
<!-- API URL Input -->
<div class="rounded-lg shadow p-6 bg-gray-800">
<h2 class="text-xl font-semibold mb-4 flex items-center">
<i class="fas fa-link mr-2 text-blue-400"></i>
API Configuration
</h2>
<div class="space-y-4">
<div>
<label class="block text-sm font-medium mb-1">API Endpoint URL</label>
<div class="flex">
<input
type="text"
placeholder="https://api.example.com/v1"
class="flex-grow px-4 py-2 border border-gray-600 rounded-l-md focus:ring-blue-500 focus:border-blue-500 bg-gray-700 text-white"
id="apiUrl">
<button
class="px-4 py-2 bg-blue-600 text-white rounded-r-md hover:bg-blue-700 transition"
id="detectBtn">
<i class="fas fa-search mr-1"></i> Detect
</button>
</div>
</div>
<!-- Authentication Section -->
<div class="pt-4 border-t border-gray-600">
<h3 class="text-lg font-medium mb-3 flex items-center">
<i class="fas fa-key mr-2 text-yellow-400"></i>
Authentication
</h3>
<div class="space-y-4">
<button id="detectAuthBtn" class="w-full py-2 px-4 bg-yellow-800 text-yellow-100 rounded-md hover:bg-yellow-700 transition flex items-center justify-center">
<i class="fas fa-search mr-2"></i> Detect Authentication Method
</button>
<div id="authOptions" class="hidden space-y-3">
<div class="flex items-center">
<input type="radio" name="authType" id="noAuth" value="none" class="focus:ring-blue-500 h-4 w-4 text-blue-600 border-gray-500">
<label for="noAuth" class="ml-2 block text-sm">No Authentication</label>
</div>
<div class="flex items-center">
<input type="radio" name="authType" id="apiKey" value="apiKey" class="focus:ring-blue-500 h-4 w-4 text-blue-600 border-gray-500">
<label for="apiKey" class="ml-2 block text-sm">API Key</label>
</div>
<div class="flex items-center">
<input type="radio" name="authType" id="oauth" value="oauth" class="focus:ring-blue-500 h-4 w-4 text-blue-600 border-gray-500">
<label for="oauth" class="ml-2 block text-sm">OAuth</label>
</div>
<div class="flex items-center">
<input type="radio" name="authType" id="basic" value="basic" class="focus:ring-blue-500 h-4 w-4 text-blue-600 border-gray-500">
<label for="basic" class="ml-2 block text-sm">Basic Auth</label>
</div>
</div>
<div id="authDetails" class="hidden space-y-4">
<!-- API Key Auth -->
<div id="apiKeyAuth" class="hidden space-y-2">
<div>
<label class="block text-sm font-medium mb-1">Key Name</label>
<input type="text" placeholder="X-API-KEY" class="w-full px-4 py-2 border border-gray-600 rounded-md bg-gray-700 text-white">
</div>
<div>
<label class="block text-sm font-medium mb-1">API Key</label>
<input type="password" placeholder="Your API Key" class="w-full px-4 py-2 border border-gray-600 rounded-md bg-gray-700 text-white">
</div>
<div>
<label class="block text-sm font-medium mb-1">Location</label>
<select class="w-full px-4 py-2 border border-gray-600 rounded-md bg-gray-700 text-white">
<option>Header</option>
<option>Query Parameter</option>
</select>
</div>
</div>
<!-- OAuth Auth -->
<div id="oauthAuth" class="hidden space-y-2">
<div>
<label class="block text-sm font-medium mb-1">Client ID</label>
<input type="text" placeholder="Your Client ID" class="w-full px-4 py-2 border border-gray-600 rounded-md bg-gray-700 text-white">
</div>
<div>
<label class="block text-sm font-medium mb-1">Client Secret</label>
<input type="password" placeholder="Your Client Secret" class="w-full px-4 py-2 border border-gray-600 rounded-md bg-gray-700 text-white">
</div>
<div>
<label class="block text-sm font-medium mb-1">Token URL</label>
<input type="text" placeholder="https://api.example.com/oauth/token" class="w-full px-4 py-2 border border-gray-600 rounded-md bg-gray-700 text-white">
</div>
</div>
<!-- Basic Auth -->
<div id="basicAuth" class="hidden space-y-2">
<div>
<label class="block text-sm font-medium mb-1">Username</label>
<input type="text" placeholder="Your username" class="w-full px-4 py-2 border border-gray-600 rounded-md bg-gray-700 text-white">
</div>
<div>
<label class="block text-sm font-medium mb-1">Password</label>
<input type="password" placeholder="Your password" class="w-full px-4 py-2 border border-gray-600 rounded-md bg-gray-700 text-white">
</div>
</div>
</div>
</div>
</div>
<!-- API Options -->
<div class="pt-4 border-t border-gray-600">
<h3 class="text-lg font-medium mb-3 flex items-center">
<i class="fas fa-cog mr-2 text-purple-400"></i>
API Options
</h3>
<div class="space-y-4">
<div>
<label class="block text-sm font-medium mb-1">Maximum Depth</label>
<select class="w-full px-4 py-2 border border-gray-600 rounded-md bg-gray-700 text-white">
<option value="1">Shallow (1 level)</option>
<option value="2" selected>Standard (2 levels)</option>
<option value="3">Deep (3 levels)</option>
<option value="0">Complete (all levels)</option>
</select>
</div>
<div>
<label class="block text-sm font-medium mb-1">Ingestion Approach</label>
<select class="w-full px-4 py-2 border border-gray-600 rounded-md bg-gray-700 text-white">
<option value="documentation">Documentation Only</option>
<option value="documentation+examples" selected>Documentation + Examples</option>
<option value="documentation+examples+code">Plus Source Code Analysis</option>
</select>
</div>
<div class="flex items-center">
<input type="checkbox" id="paginationCheck" class="focus:ring-blue-500 h-4 w-4 text-blue-600 border-gray-500">
<label for="paginationCheck" class="ml-2 block text-sm">Include Pagination Logic</label>
</div>
</div>
</div>
</div>
</div>
<!-- Detection Buttons -->
<div class="rounded-lg shadow p-6 bg-gray-800">
<h2 class="text-xl font-semibold mb-4 flex items-center">
<i class="fas fa-magic mr-2 text-green-400"></i>
Auto-Detection
</h2>
<div class="grid grid-cols-1 md:grid-cols-2 gap-3">
<button id="detectMethodsBtn" class="flex items-center justify-center px-4 py-3 bg-blue-900 text-blue-100 rounded-md hover:bg-blue-800 transition">
<i class="fas fa-random mr-2"></i> Detect Call Methods
</button>
<button id="detectProtocolBtn" class="flex items-center justify-center px-4 py-3 bg-purple-900 text-purple-100 rounded-md hover:bg-purple-800 transition">
<i class="fas fa-plug mr-2"></i> Detect Protocol
</button>
<button id="detectStructureBtn" class="flex items-center justify-center px-4 py-3 bg-indigo-900 text-indigo-100 rounded-md hover:bg-indigo-800 transition">
<i class="fas fa-sitemap mr-2"></i> Detect Structure
</button>
<button id="detectPaginationBtn" class="flex items-center justify-center px-4 py-3 bg-pink-900 text-pink-100 rounded-md hover:bg-pink-800 transition">
<i class="fas fa-copy mr-2"></i> Detect Pagination
</button>
</div>
</div>
</div>
<!-- Right Panel - Results and Helper Mode -->
<div class="md:col-span-2 space-y-6">
<!-- Output Console -->
<div class="rounded-lg shadow h-full bg-gray-800">
<div class="p-4 border-b border-gray-600">
<h2 class="text-xl font-semibold flex items-center">
<i class="fas fa-terminal mr-2 text-gray-400"></i>
Ingestion Console
</h2>
</div>
<div class="p-4">
<div id="consoleOutput" class="h-64 overflow-y-auto scrollbar-hide bg-gray-700 rounded-md p-3 text-sm font-mono space-y-2">
<div class="text-gray-400">Ready to begin API ingestion process...</div>
</div>
</div>
<div class="p-4 border-t border-gray-600 flex justify-between">
<button id="startIngestionBtn" class="px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700 transition flex items-center">
<i class="fas fa-play mr-2"></i> Start Ingestion
</button>
<button id="helperModeBtn" class="px-4 py-2 bg-indigo-600 text-white rounded-md hover:bg-indigo-700 transition hidden flex items-center">
<i class="fas fa-robot mr-2"></i> Enter Helper Mode
</button>
</div>
</div>
<!-- Detected Information -->
<div id="detectedInfo" class="rounded-lg shadow hidden overflow-hidden bg-gray-800">
<div class="p-4 border-b border-gray-600 bg-amber-900">
<h2 class="text-xl font-semibold flex items-center justify-between">
<span><i class="fas fa-info-circle mr-2 text-amber-400"></i> Detected Information</span>
<button id="closeDetectedInfo" class="text-gray-400 hover:text-gray-200">
<i class="fas fa-times"></i>
</button>
</h2>
</div>
<div class="p-4">
<div class="json-viewer text-gray-300 p-4 overflow-auto max-h-60">
<pre id="detectedJson">No information detected yet.</pre>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Helper Mode Modal -->
<div id="helperModal" class="fixed inset-0 bg-black bg-opacity-70 flex items-center justify-center z-50 hidden">
<div class="bg-gray-800 rounded-lg shadow-xl w-full max-w-4xl max-h-[90vh] flex flex-col">
<div class="p-4 border-b border-gray-600 bg-indigo-900">
<h2 class="text-xl font-semibold">
<i class="fas fa-robot mr-2 text-indigo-400"></i> API Helper Mode
</h2>
</div>
<div class="flex-1 overflow-hidden flex flex-col">
<div id="chatContainer" class="flex-1 overflow-y-auto p-4 space-y-4 scrollbar-hide bg-gray-700">
<div class="flex justify-start">
<div class="max-w-[80%] bg-indigo-800 p-3 rounded-lg">
I've successfully ingested the API documentation. How can I help you work with this API?
</div>
</div>
</div>
<div class="p-4 border-t border-gray-600">
<div class="flex">
<input type="text" id="userQuery" placeholder="Ask me anything about this API..." class="flex-grow px-4 py-2 border border-gray-600 rounded-l-md focus:ring-indigo-500 focus:border-indigo-500 bg-gray-700 text-white">
<button id="sendQueryBtn" class="px-4 py-2 bg-indigo-600 text-white rounded-r-md hover:bg-indigo-700 transition">
<i class="fas fa-paper-plane"></i>
</button>
</div>
</div>
</div>
<div class="p-4 border-t border-gray-600 flex justify-end">
<button id="exitHelperBtn" class="px-4 py-2 bg-gray-700 text-white rounded-md hover:bg-gray-600 transition">
Exit Helper Mode
</button>
</div>
</div>
</div>
<script>
// DOM Elements
const apiUrlInput = document.getElementById('apiUrl');
const detectBtn = document.getElementById('detectBtn');
const detectAuthBtn = document.getElementById('detectAuthBtn');
const authOptions = document.getElementById('authOptions');
const authDetails = document.getElementById('authDetails');
const consoleOutput = document.getElementById('consoleOutput');
const startIngestionBtn = document.getElementById('startIngestionBtn');
const helperModeBtn = document.getElementById('helperModeBtn');
const detectedInfo = document.getElementById('detectedInfo');
const detectedJson = document.getElementById('detectedJson');
const closeDetectedInfo = document.getElementById('closeDetectedInfo');
const helperModal = document.getElementById('helperModal');
const exitHelperBtn = document.getElementById('exitHelperBtn');
const userQuery = document.getElementById('userQuery');
const sendQueryBtn = document.getElementById('sendQueryBtn');
const chatContainer = document.getElementById('chatContainer');
// Detection buttons
const detectMethodsBtn = document.getElementById('detectMethodsBtn');
const detectProtocolBtn = document.getElementById('detectProtocolBtn');
const detectStructureBtn = document.getElementById('detectStructureBtn');
const detectPaginationBtn = document.getElementById('detectPaginationBtn');
// Auth type radio buttons
const authRadios = document.querySelectorAll('input[name="authType"]');
const apiKeyAuth = document.getElementById('apiKeyAuth');
const oauthAuth = document.getElementById('oauthAuth');
const basicAuth = document.getElementById('basicAuth');
// Detect API URL
detectBtn.addEventListener('click', () => {
const url = apiUrlInput.value.trim();
if (!url) {
logToConsole('Please enter a valid API URL', 'error');
return;
}
logToConsole(`Detecting API at: ${url}`, 'info');
apiUrlInput.disabled = true;
detectBtn.disabled = true;
detectBtn.innerHTML = '<i class="fas fa-spinner fa-spin mr-1"></i> Detecting...';
// Simulate API detection
setTimeout(() => {
logToConsole('API endpoint detected successfully', 'success');
detectBtn.innerHTML = '<i class="fas fa-check mr-1"></i> Detected';
detectAuthBtn.disabled = false;
authOptions.classList.remove('hidden');
// Enable all detection buttons
[detectMethodsBtn, detectProtocolBtn, detectStructureBtn, detectPaginationBtn].forEach(btn => {
btn.disabled = false;
});
}, 2000);
});
// Detect authentication type
detectAuthBtn.addEventListener('click', () => {
logToConsole('Detecting authentication method...', 'info');
detectAuthBtn.disabled = true;
detectAuthBtn.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i> Detecting...';
// Simulate auth detection
setTimeout(() => {
logToConsole('Authentication method detected: API Key', 'success');
detectAuthBtn.classList.add('hidden');
authOptions.classList.remove('hidden');
authDetails.classList.remove('hidden');
document.getElementById('apiKey').checked = true;
apiKeyAuth.classList.remove('hidden');
}, 1500);
});
// Handle auth type selection
authRadios.forEach(radio => {
radio.addEventListener('change', () => {
apiKeyAuth.classList.add('hidden');
oauthAuth.classList.add('hidden');
basicAuth.classList.add('hidden');
if (radio.value === 'apiKey') {
apiKeyAuth.classList.remove('hidden');
} else if (radio.value === 'oauth') {
oauthAuth.classList.remove('hidden');
} else if (radio.value === 'basic') {
basicAuth.classList.remove('hidden');
}
});
});
// Detection buttons
detectMethodsBtn.addEventListener('click', () => simulateDetection('API call methods', 'GET, POST, PUT, DELETE available'));
detectProtocolBtn.addEventListener('click', () => simulateDetection('API protocol', 'REST API detected'));
detectStructureBtn.addEventListener('click', () => simulateDetection('API structure', 'Hierarchical resource structure detected'));
detectPaginationBtn.addEventListener('click', () => simulateDetection('Pagination method', 'Offset-based pagination detected'));
// Start ingestion process
startIngestionBtn.addEventListener('click', () => {
const url = apiUrlInput.value.trim();
if (!url) {
logToConsole('Please configure the API first', 'error');
return;
}
logToConsole('Starting API ingestion process...', 'info');
startIngestionBtn.disabled = true;
startIngestionBtn.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i> Processing...';
// Simulate ingestion process
setTimeout(() => {
logToConsole('Discovering API endpoints...', 'processing');
}, 1000);
setTimeout(() => {
logToConsole('Analyzing request/response patterns...', 'processing');
}, 3000);
setTimeout(() => {
logToConsole('Extracting documentation...', 'processing');
], 5000);
setTimeout(() => {
logToConsole('Identifying relationships between endpoints...', 'processing');
}, 8000);
setTimeout(() => {
logToConsole('Successfully ingested API documentation!', 'success');
startIngestionBtn.classList.add('hidden');
helperModeBtn.classList.remove('hidden');
// Show sample detected info
const sampleData = {
api: {
baseUrl: url,
authentication: "API Key (X-API-KEY in header)",
endpoints: [
{
path: "/users",
methods: ["GET", "POST"],
description: "Manage user accounts",
parameters: {
GET: {
limit: "number",
offset: "number"
},
POST: {
name: "string",
email: "string"
}
}
},
{
path: "/users/{id}",
methods: ["GET", "PUT", "DELETE"],
description: "Specific user operations"
}
],
pagination: "offset-based (limit/offset)",
rateLimiting: "100 requests/minute"
}
};
detectedJson.textContent = JSON.stringify(sampleData, null, 2);
showDetectedInfo();
}, 10000);
});
// Helper mode
helperModeBtn.addEventListener('click', () => {
helperModal.classList.remove('hidden');
});
exitHelperBtn.addEventListener('click', () => {
helperModal.classList.add('hidden');
});
// Close detected info
closeDetectedInfo.addEventListener('click', () => {
detectedInfo.classList.add('hidden');
});
// Chat functionality
sendQueryBtn.addEventListener('click', sendMessage);
userQuery.addEventListener('keypress', (e) => {
if (e.key === 'Enter') sendMessage();
});
function sendMessage() {
const message = userQuery.value.trim();
if (!message) return;
// Add user message
addMessage('user', message);
userQuery.value = '';
// Simulate AI response
setTimeout(() => {
const responses = [
"For that functionality, you'll want to use the /users endpoint with a POST method.",
"The API documentation shows that you can use pagination with limit and offset parameters.",
"I can generate sample code for you to call this endpoint in JavaScript."
];
const randomResponse = responses[Math.floor(Math.random() * responses.length)];
addMessage('ai', randomResponse);
}, 1000);
}
// Utility functions
function simulateDetection(name, result) {
const btn = event.target;
btn.disabled = true;
const originalText = btn.innerHTML;
btn.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i>';
setTimeout(() => {
logToConsole(`${name} detected: ${result}`, 'success');
btn.innerHTML = originalText;
}, 2000);
}
function logToConsole(message, type = 'info') {
const timestamp = new Date().toLocaleTimeString();
let icon, color;
switch(type) {
case 'error':
icon = '<i class="fas fa-exclamation-circle text-red-400 mr-2"></i>';
color = 'text-red-400';
break;
case 'success':
icon = '<i class="fas fa-check-circle text-green-400 mr-2"></i>';
color = 'text-green-400';
break;
case 'processing':
icon = '<i class="fas fa-spinner fa-spin text-blue-400 mr-2"></i>';
color = 'text-blue-400';
break;
default:
icon = '<i class="fas fa-info-circle text-gray-400 mr-2"></i>';
color = 'text-gray-400';
}
const entry = document.createElement('div');
entry.className = 'flex items-start';
entry.innerHTML = `
<span class="text-xs text-gray-500 mr-2">[${timestamp}]</span>
<span class="${color}">${icon}</span>
<span class="${color} flex-1">${message}</span>
`;
consoleOutput.appendChild(entry);
consoleOutput.scrollTop = consoleOutput.scrollHeight;
}
function showDetectedInfo() {
detectedInfo.classList.remove('hidden');
}
function addMessage(sender, text) {
const messageDiv = document.createElement('div');
if (sender === 'user') {
messageDiv.className = 'flex justify-end';
messageDiv.innerHTML = `
<div class="max_w-[80%] bg-blue-600 text-white p-3 rounded-lg">
${text}
</div>
`;
} else {
messageDiv.className = 'flex justify-start';
messageDiv.innerHTML = `
<div class="max-w-[80%] bg-indigo-800 text-gray-200 p-3 rounded-lg">
${text}
</div>
`;
}
chatContainer.appendChild(messageDiv);
chatContainer.scrollTop = chatContainer.scrollHeight;
}
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=aegisceo/apiingest-lite" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>