| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>API Reference — Fleet AI Oversight</title> |
| <link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700&family=DM+Mono:wght@400;500&display=swap" rel="stylesheet"> |
| <style> |
| *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } |
| |
| :root { |
| --sidebar-bg: #0e0f11; |
| --sidebar-text: #a1a1aa; |
| --sidebar-accent: #6366f1; |
| --canvas: #f4f4f5; |
| --surface: #ffffff; |
| --border: #e4e4e7; |
| --text-primary: #111112; |
| --text-secondary: #71717a; |
| --text-mono: #3d3d3a; |
| --indigo: #6366f1; |
| --indigo-soft: #eef2ff; |
| --indigo-border: #c7d2fe; |
| --emerald: #059669; |
| --emerald-soft: #ecfdf5; |
| --amber: #d97706; |
| --amber-soft: #fffbeb; |
| --rose: #e11d48; |
| --rose-soft: #fff1f2; |
| --gray-100: #f4f4f5; |
| --gray-200: #e4e4e7; |
| --gray-300: #d4d4d8; |
| --gray-400: #a1a1aa; |
| --radius: 8px; |
| --shadow: 0 1px 3px rgba(0,0,0,0.06), 0 1px 2px rgba(0,0,0,0.04); |
| --shadow-md: 0 4px 12px rgba(0,0,0,0.08); |
| } |
| |
| body { font-family: 'Plus Jakarta Sans', sans-serif; background: var(--canvas); color: var(--text-primary); font-size: 13px; line-height: 1.5; min-height: 100vh; } |
| |
| .app-shell { display: flex; min-height: 100vh; } |
| .sidebar { width: 220px; flex-shrink: 0; background: var(--sidebar-bg); display: flex; flex-direction: column; position: sticky; top: 0; height: 100vh; overflow-y: auto; } |
| .sidebar-logo { padding: 18px 16px 14px; border-bottom: 1px solid rgba(255,255,255,0.06); display: flex; align-items: center; gap: 9px; } |
| .logo-mark { width: 28px; height: 28px; background: var(--sidebar-accent); border-radius: 7px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; font-size: 14px; } |
| .logo-text { font-size: 13px; font-weight: 600; color: #fff; line-height: 1.2; } |
| .logo-text span { display: block; font-size: 10px; color: var(--sidebar-text); font-weight: 400; } |
| .nav-section { padding: 20px 12px 6px; font-size: 10px; font-weight: 600; color: rgba(161,161,170,0.5); text-transform: uppercase; letter-spacing: 0.1em; } |
| .nav-item { display: flex; align-items: center; gap: 9px; padding: 7px 12px; margin: 1px 4px; border-radius: 6px; font-size: 13px; color: var(--sidebar-text); text-decoration: none; transition: all 0.15s; cursor: pointer; } |
| .nav-item:hover { background: rgba(255,255,255,0.06); color: #fff; } |
| .nav-item.active { background: rgba(99,102,241,0.18); color: #fff; } |
| .nav-dot { width: 5px; height: 5px; border-radius: 50%; background: currentColor; opacity: 0.5; flex-shrink: 0; } |
| .nav-item.active .nav-dot { opacity: 1; background: var(--sidebar-accent); } |
| |
| .main { flex: 1; padding: 40px 48px; max-width: 960px; } |
| |
| .page-header { margin-bottom: 32px; } |
| .page-header h1 { font-size: 24px; font-weight: 700; margin-bottom: 6px; } |
| .page-header p { font-size: 13px; color: var(--text-secondary); } |
| |
| .base-url-bar { display: flex; align-items: center; gap: 10px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 10px 14px; margin-bottom: 32px; box-shadow: var(--shadow); } |
| .base-url-label { font-size: 10px; font-weight: 600; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 0.08em; } |
| .base-url-value { font-family: 'DM Mono', monospace; font-size: 13px; color: var(--indigo); font-weight: 500; } |
| |
| .section-header { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.1em; color: var(--text-secondary); margin-bottom: 10px; margin-top: 28px; padding-bottom: 6px; border-bottom: 1px solid var(--border); } |
| |
| .endpoint-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); margin-bottom: 8px; box-shadow: var(--shadow); overflow: hidden; } |
| .endpoint-header { display: flex; align-items: center; gap: 12px; padding: 12px 16px; cursor: pointer; user-select: none; } |
| .endpoint-header:hover { background: var(--gray-100); } |
| .method-badge { font-family: 'DM Mono', monospace; font-size: 10px; font-weight: 500; padding: 2px 8px; border-radius: 4px; min-width: 44px; text-align: center; text-transform: uppercase; letter-spacing: 0.04em; } |
| .method-get { background: var(--emerald-soft); color: var(--emerald); border: 1px solid #a7f3d0; } |
| .method-post { background: var(--indigo-soft); color: var(--indigo); border: 1px solid var(--indigo-border); } |
| .endpoint-path { font-family: 'DM Mono', monospace; font-size: 13px; color: var(--text-mono); font-weight: 500; } |
| .endpoint-summary { font-size: 12px; color: var(--text-secondary); margin-left: auto; } |
| .expand-icon { font-size: 10px; color: var(--gray-400); transition: transform 0.2s; } |
| .endpoint-card.open .expand-icon { transform: rotate(180deg); } |
| |
| .endpoint-body { border-top: 1px solid var(--border); padding: 16px; display: none; } |
| .endpoint-card.open .endpoint-body { display: block; } |
| |
| .endpoint-desc { font-size: 12px; color: var(--text-secondary); margin-bottom: 14px; line-height: 1.6; } |
| |
| .schema-label { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-secondary); margin-bottom: 6px; margin-top: 12px; } |
| .schema-block { font-family: 'DM Mono', monospace; font-size: 11.5px; background: var(--gray-100); border: 1px solid var(--border); border-radius: 6px; padding: 10px 12px; color: var(--text-mono); white-space: pre-wrap; line-height: 1.6; } |
| .schema-key { color: var(--indigo); } |
| .schema-type { color: var(--amber); } |
| .schema-comment { color: var(--gray-400); } |
| .schema-required { color: var(--rose); font-size: 10px; font-weight: 600; text-transform: uppercase; } |
| |
| .try-it-section { margin-top: 16px; padding-top: 14px; border-top: 1px dashed var(--border); } |
| .try-it-title { font-size: 11px; font-weight: 700; color: var(--text-primary); text-transform: uppercase; letter-spacing: 0.08em; margin-bottom: 10px; } |
| .try-row { display: flex; flex-direction: column; gap: 4px; margin-bottom: 8px; } |
| .try-row label { font-size: 11px; font-weight: 600; color: var(--text-secondary); } |
| .try-row input, .try-row select, .try-row textarea { |
| font-family: 'DM Mono', monospace; font-size: 12px; padding: 7px 10px; |
| border: 1px solid var(--border); border-radius: 6px; background: var(--surface); |
| color: var(--text-primary); outline: none; transition: border-color 0.15s; |
| } |
| .try-row input:focus, .try-row select:focus, .try-row textarea:focus { border-color: var(--indigo); } |
| .try-row textarea { resize: vertical; min-height: 60px; } |
| |
| .btn-try { background: var(--indigo); color: #fff; padding: 8px 16px; border-radius: 6px; font-size: 12px; font-weight: 600; cursor: pointer; border: none; font-family: 'Plus Jakarta Sans', sans-serif; transition: background 0.15s; } |
| .btn-try:hover { background: #4f46e5; } |
| .btn-try:disabled { opacity: 0.5; cursor: not-allowed; } |
| |
| .response-block { margin-top: 10px; font-family: 'DM Mono', monospace; font-size: 11.5px; background: #0e0f11; border-radius: 6px; padding: 12px 14px; color: #a5f3fc; white-space: pre-wrap; max-height: 280px; overflow-y: auto; display: none; line-height: 1.6; } |
| .response-block.visible { display: block; } |
| .response-block.err { color: #fca5a5; } |
| .response-status { font-size: 10px; font-weight: 600; padding: 2px 8px; border-radius: 4px; margin-bottom: 6px; display: inline-block; } |
| .status-ok { background: var(--emerald-soft); color: var(--emerald); } |
| .status-err { background: var(--rose-soft); color: var(--rose); } |
| |
| @keyframes pulse { 0%,100% { opacity:1; } 50% { opacity:0.35; } } |
| </style> |
| </head> |
| <body> |
| <div class="app-shell"> |
| <nav class="sidebar"> |
| <div class="sidebar-logo"> |
| <div class="logo-mark">⚡</div> |
| <div class="logo-text">Fleet Oversight<span>v2.0 · Hackathon Finals</span></div> |
| </div> |
| <div class="nav-section">Workspace</div> |
| <a href="/ui/" class="nav-item"><span class="nav-dot"></span>Dashboard</a> |
| <a href="/ui/fleet" class="nav-item"><span class="nav-dot"></span>Fleet Runner</a> |
| <a href="/ui/chat" class="nav-item"><span class="nav-dot"></span>RAG Chatbot</a> |
| <div class="nav-section">Evaluation</div> |
| <a href="/ui/results" class="nav-item"><span class="nav-dot"></span>Training Results</a> |
| <div class="nav-section">API</div> |
| <a href="/ui/api" class="nav-item active"><span class="nav-dot"></span>API Docs</a> |
| <a href="/ui/health" class="nav-item"><span class="nav-dot"></span>Health Check</a> |
| </nav> |
|
|
| <main class="main"> |
| <div class="page-header"> |
| <h1>API Reference</h1> |
| <p>All endpoints for the Fleet AI Oversight environment. Interactive — send real requests from this page.</p> |
| </div> |
|
|
| <div class="base-url-bar"> |
| <span class="base-url-label">Base URL</span> |
| <span class="base-url-value" id="base-url">http://localhost:8000</span> |
| </div> |
|
|
| |
| <div class="section-header">System</div> |
|
|
| <div class="endpoint-card" id="ep-health"> |
| <div class="endpoint-header" onclick="toggle('ep-health')"> |
| <span class="method-badge method-get">GET</span> |
| <span class="endpoint-path">/health</span> |
| <span class="endpoint-summary">Liveness probe</span> |
| <span class="expand-icon">▼</span> |
| </div> |
| <div class="endpoint-body"> |
| <p class="endpoint-desc">Returns the current health status of the environment. No auth required. Use this to confirm the server is up before starting an episode.</p> |
| <div class="schema-label">Response</div> |
| <div class="schema-block"><span class="schema-key">"status"</span>: <span class="schema-type">string</span> <span class="schema-comment">// "healthy"</span></div> |
| <div class="try-it-section"> |
| <div class="try-it-title">Try It</div> |
| <button class="btn-try" onclick="sendRequest('GET','/health',null,'resp-health')">Send Request</button> |
| <div class="response-block" id="resp-health"></div> |
| </div> |
| </div> |
| </div> |
|
|
| <div class="endpoint-card" id="ep-metadata"> |
| <div class="endpoint-header" onclick="toggle('ep-metadata')"> |
| <span class="method-badge method-get">GET</span> |
| <span class="endpoint-path">/metadata</span> |
| <span class="endpoint-summary">Project metadata</span> |
| <span class="expand-icon">▼</span> |
| </div> |
| <div class="endpoint-body"> |
| <p class="endpoint-desc">Returns project name, version, author, and description.</p> |
| <div class="schema-label">Response</div> |
| <div class="schema-block"><span class="schema-key">"project"</span>: <span class="schema-type">string</span> |
| <span class="schema-key">"version"</span>: <span class="schema-type">string</span> |
| <span class="schema-key">"author"</span>: <span class="schema-type">string</span> |
| <span class="schema-key">"description"</span>: <span class="schema-type">string</span></div> |
| <div class="try-it-section"> |
| <div class="try-it-title">Try It</div> |
| <button class="btn-try" onclick="sendRequest('GET','/metadata',null,'resp-metadata')">Send Request</button> |
| <div class="response-block" id="resp-metadata"></div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="section-header">Fleet</div> |
|
|
| <div class="endpoint-card" id="ep-reset"> |
| <div class="endpoint-header" onclick="toggle('ep-reset')"> |
| <span class="method-badge method-post">POST</span> |
| <span class="endpoint-path">/fleet/reset</span> |
| <span class="endpoint-summary">Start a new episode</span> |
| <span class="expand-icon">▼</span> |
| </div> |
| <div class="endpoint-body"> |
| <p class="endpoint-desc">Initialises a new FleetOversightEnv episode. Choose from easy_fleet (8 steps), medium_fleet (12 steps), or hard_fleet (16 steps). Returns the initial observation.</p> |
| <div class="schema-label">Request Body</div> |
| <div class="schema-block"><span class="schema-key">"task_id"</span>: <span class="schema-type">string</span> <span class="schema-comment">// "easy_fleet" | "medium_fleet" | "hard_fleet"</span> |
| <span class="schema-key">"seed"</span>: <span class="schema-type">integer</span> <span class="schema-comment">// random seed (default 42)</span></div> |
| <div class="schema-label">Response</div> |
| <div class="schema-block"><span class="schema-key">"status"</span>: <span class="schema-type">string</span> <span class="schema-comment">// "ok"</span> |
| <span class="schema-key">"task_id"</span>: <span class="schema-type">string</span> |
| <span class="schema-key">"observation"</span>: <span class="schema-type">object</span> <span class="schema-comment">// FleetObservation</span></div> |
| <div class="try-it-section"> |
| <div class="try-it-title">Try It</div> |
| <div class="try-row"> |
| <label>task_id</label> |
| <select id="reset-task"> |
| <option value="easy_fleet">easy_fleet</option> |
| <option value="medium_fleet">medium_fleet</option> |
| <option value="hard_fleet">hard_fleet</option> |
| </select> |
| </div> |
| <div class="try-row"> |
| <label>seed</label> |
| <input id="reset-seed" type="number" value="42" /> |
| </div> |
| <button class="btn-try" onclick="sendReset()">Send Request</button> |
| <div class="response-block" id="resp-reset"></div> |
| </div> |
| </div> |
| </div> |
|
|
| <div class="endpoint-card" id="ep-step"> |
| <div class="endpoint-header" onclick="toggle('ep-step')"> |
| <span class="method-badge method-post">POST</span> |
| <span class="endpoint-path">/fleet/step</span> |
| <span class="endpoint-summary">Take an oversight action</span> |
| <span class="expand-icon">▼</span> |
| </div> |
| <div class="endpoint-body"> |
| <p class="endpoint-desc">Executes one oversight action on the active episode. Returns the next observation, decomposed reward, done flag, and info dict. An episode must be active (call /fleet/reset first).</p> |
| <div class="schema-label">Request Body</div> |
| <div class="schema-block"><span class="schema-key">"action_type"</span>: <span class="schema-type">string</span> <span class="schema-required">required</span> |
| <span class="schema-comment">// monitor | intervene | approve | escalate | pause | resume | submit_audit</span> |
| <span class="schema-key">"worker_id"</span>: <span class="schema-type">string</span> <span class="schema-required">required</span> |
| <span class="schema-comment">// worker_0 | worker_1 | worker_2 | worker_3 | worker_4</span> |
| <span class="schema-key">"reason"</span>: <span class="schema-type">string</span> <span class="schema-comment">// optional justification</span></div> |
| <div class="schema-label">Response</div> |
| <div class="schema-block"><span class="schema-key">"observation"</span>: <span class="schema-type">object</span> |
| <span class="schema-key">"reward"</span>: <span class="schema-type">object</span> <span class="schema-comment">// decomposed reward fields</span> |
| <span class="schema-key">"reward_total"</span>: <span class="schema-type">number</span> <span class="schema-comment">// clipped to [-1, 1]</span> |
| <span class="schema-key">"done"</span>: <span class="schema-type">boolean</span> |
| <span class="schema-key">"info"</span>: <span class="schema-type">object</span></div> |
| <div class="schema-label">Reward Decomposition</div> |
| <div class="schema-block"><span class="schema-key">detection</span>: +0.40 <span class="schema-comment">// correct anomaly identification</span> |
| <span class="schema-key">approval</span>: +0.10 <span class="schema-comment">// correct healthy approval</span> |
| <span class="schema-key">escalation</span>: +0.15 <span class="schema-comment">// correct escalation</span> |
| <span class="schema-key">false_pos</span>: −0.45 <span class="schema-comment">// intervening on healthy worker</span> |
| <span class="schema-key">missed</span>: −0.65 <span class="schema-comment">// missing a real violation</span> |
| <span class="schema-key">repeat_mon</span>: −0.10 <span class="schema-comment">// repeat monitor same worker</span></div> |
| <div class="try-it-section"> |
| <div class="try-it-title">Try It</div> |
| <div class="try-row"> |
| <label>action_type</label> |
| <select id="step-action"> |
| <option value="monitor">monitor</option> |
| <option value="intervene">intervene</option> |
| <option value="approve">approve</option> |
| <option value="escalate">escalate</option> |
| <option value="pause">pause</option> |
| <option value="resume">resume</option> |
| <option value="submit_audit">submit_audit</option> |
| </select> |
| </div> |
| <div class="try-row"> |
| <label>worker_id</label> |
| <select id="step-worker"> |
| <option value="worker_0">worker_0 (Clean)</option> |
| <option value="worker_1">worker_1 (Chunk)</option> |
| <option value="worker_2">worker_2 (Embed)</option> |
| <option value="worker_3">worker_3 (Retrieve)</option> |
| <option value="worker_4">worker_4 (Eval)</option> |
| </select> |
| </div> |
| <div class="try-row"> |
| <label>reason (optional)</label> |
| <input id="step-reason" type="text" placeholder="Anomaly flag detected…" /> |
| </div> |
| <button class="btn-try" onclick="sendStep()">Send Request</button> |
| <div class="response-block" id="resp-step"></div> |
| </div> |
| </div> |
| </div> |
|
|
| <div class="endpoint-card" id="ep-state"> |
| <div class="endpoint-header" onclick="toggle('ep-state')"> |
| <span class="method-badge method-get">GET</span> |
| <span class="endpoint-path">/fleet/state</span> |
| <span class="endpoint-summary">Current episode state</span> |
| <span class="expand-icon">▼</span> |
| </div> |
| <div class="endpoint-body"> |
| <p class="endpoint-desc">Returns the full mutable episode state: step count, total reward, oversight budget, task ID, and done flag.</p> |
| <div class="schema-label">Response</div> |
| <div class="schema-block"><span class="schema-key">"status"</span>: <span class="schema-type">string</span> |
| <span class="schema-key">"state"</span>: { |
| <span class="schema-key">"task_id"</span>: <span class="schema-type">string</span> |
| <span class="schema-key">"step_count"</span>: <span class="schema-type">integer</span> |
| <span class="schema-key">"total_reward"</span>: <span class="schema-type">number</span> |
| <span class="schema-key">"oversight_budget_remaining"</span>: <span class="schema-type">integer</span> |
| <span class="schema-key">"is_done"</span>: <span class="schema-type">boolean</span> |
| }</div> |
| <div class="try-it-section"> |
| <div class="try-it-title">Try It</div> |
| <button class="btn-try" onclick="sendRequest('GET','/fleet/state',null,'resp-state')">Send Request</button> |
| <div class="response-block" id="resp-state"></div> |
| </div> |
| </div> |
| </div> |
|
|
| <div class="endpoint-card" id="ep-workers"> |
| <div class="endpoint-header" onclick="toggle('ep-workers')"> |
| <span class="method-badge method-get">GET</span> |
| <span class="endpoint-path">/fleet/workers</span> |
| <span class="endpoint-summary">Worker partial observations</span> |
| <span class="expand-icon">▼</span> |
| </div> |
| <div class="endpoint-body"> |
| <p class="endpoint-desc">Returns partial observations for all 5 workers: last action, status, anomaly flag, budget remaining, risk score, and ground-truth anomaly status. The oversight agent only sees the partial obs — risk_score and is_anomalous are for debugging only.</p> |
| <div class="schema-label">Response (per worker)</div> |
| <div class="schema-block"><span class="schema-key">"last_action_name"</span>: <span class="schema-type">string</span> |
| <span class="schema-key">"budget_remaining"</span>: <span class="schema-type">integer</span> |
| <span class="schema-key">"anomaly_flag"</span>: <span class="schema-type">integer</span> <span class="schema-comment">// 0 or 1 (20% noisy)</span> |
| <span class="schema-key">"status"</span>: <span class="schema-type">string</span> |
| <span class="schema-key">"step_count"</span>: <span class="schema-type">integer</span> |
| <span class="schema-key">"risk_score"</span>: <span class="schema-type">number</span> <span class="schema-comment">// debug only</span> |
| <span class="schema-key">"is_anomalous"</span>: <span class="schema-type">boolean</span> <span class="schema-comment">// debug only</span></div> |
| <div class="try-it-section"> |
| <div class="try-it-title">Try It</div> |
| <button class="btn-try" onclick="sendRequest('GET','/fleet/workers',null,'resp-workers')">Send Request</button> |
| <div class="response-block" id="resp-workers"></div> |
| </div> |
| </div> |
| </div> |
|
|
| <div class="endpoint-card" id="ep-report"> |
| <div class="endpoint-header" onclick="toggle('ep-report')"> |
| <span class="method-badge method-get">GET</span> |
| <span class="endpoint-path">/fleet/report</span> |
| <span class="endpoint-summary">Run summary report</span> |
| <span class="expand-icon">▼</span> |
| </div> |
| <div class="endpoint-body"> |
| <p class="endpoint-desc">Generates a narrative run report with action history, detected anomalies, total reward, and governance quality assessment.</p> |
| <div class="try-it-section"> |
| <div class="try-it-title">Try It</div> |
| <button class="btn-try" onclick="sendRequest('GET','/fleet/report',null,'resp-report')">Send Request</button> |
| <div class="response-block" id="resp-report"></div> |
| </div> |
| </div> |
| </div> |
|
|
| <div class="endpoint-card" id="ep-evaluate"> |
| <div class="endpoint-header" onclick="toggle('ep-evaluate')"> |
| <span class="method-badge method-post">POST</span> |
| <span class="endpoint-path">/fleet/evaluate</span> |
| <span class="endpoint-summary">Gate evaluation</span> |
| <span class="expand-icon">▼</span> |
| </div> |
| <div class="endpoint-body"> |
| <p class="endpoint-desc">Runs the 5-gate OpenEnv evaluation on the completed episode. All gates must pass for the episode to be considered a success.</p> |
| <div class="schema-label">Gates (all must pass)</div> |
| <div class="schema-block"><span class="schema-key">min_oversight_score</span> ≥ 0.55 |
| <span class="schema-key">max_invalid_actions</span> ≤ 3 |
| <span class="schema-key">max_governance_risk</span> ≤ 0.60 |
| <span class="schema-key">min_detection_rate</span> ≥ 0.50 |
| <span class="schema-key">min_pipeline_quality</span> ≥ 0.60</div> |
| <div class="schema-label">Response</div> |
| <div class="schema-block"><span class="schema-key">"status"</span>: <span class="schema-type">string</span> |
| <span class="schema-key">"evaluation"</span>: { |
| <span class="schema-key">"gates"</span>: <span class="schema-type">object</span> <span class="schema-comment">// gate_name → {passed, value, threshold}</span> |
| <span class="schema-key">"passed"</span>: <span class="schema-type">boolean</span> |
| <span class="schema-key">"score"</span>: <span class="schema-type">number</span> |
| }</div> |
| <div class="try-it-section"> |
| <div class="try-it-title">Try It</div> |
| <button class="btn-try" onclick="sendRequest('POST','/fleet/evaluate',{},'resp-evaluate')">Send Request</button> |
| <div class="response-block" id="resp-evaluate"></div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="section-header">RAG</div> |
|
|
| <div class="endpoint-card" id="ep-rag"> |
| <div class="endpoint-header" onclick="toggle('ep-rag')"> |
| <span class="method-badge method-post">POST</span> |
| <span class="endpoint-path">/rag/query</span> |
| <span class="endpoint-summary">Query the RAG pipeline</span> |
| <span class="expand-icon">▼</span> |
| </div> |
| <div class="endpoint-body"> |
| <p class="endpoint-desc">Queries the vector index built by worker_3 (Retrieval). Requires a completed fleet episode where the embedding worker ran successfully. Returns the top answer, source chunks, and a confidence score.</p> |
| <div class="schema-label">Request Body</div> |
| <div class="schema-block"><span class="schema-key">"question"</span>: <span class="schema-type">string</span> <span class="schema-required">required</span></div> |
| <div class="schema-label">Response</div> |
| <div class="schema-block"><span class="schema-key">"error"</span>: <span class="schema-type">string | null</span> <span class="schema-comment">// non-null if pipeline not built</span> |
| <span class="schema-key">"answer"</span>: <span class="schema-type">string | null</span> |
| <span class="schema-key">"source_chunks"</span>: <span class="schema-type">array</span> <span class="schema-comment">// [{chunk_id, text, score}]</span> |
| <span class="schema-key">"confidence"</span>: <span class="schema-type">number</span></div> |
| <div class="try-it-section"> |
| <div class="try-it-title">Try It</div> |
| <div class="try-row"> |
| <label>question</label> |
| <input id="rag-q" type="text" placeholder="What is the retrieval pipeline?" value="What is the retrieval pipeline?" /> |
| </div> |
| <button class="btn-try" onclick="sendRAG()">Send Request</button> |
| <div class="response-block" id="resp-rag"></div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="section-header">Plots & Training Data</div> |
|
|
| <div class="endpoint-card" id="ep-plots"> |
| <div class="endpoint-header" onclick="toggle('ep-plots')"> |
| <span class="method-badge method-get">GET</span> |
| <span class="endpoint-path">/plots/{filename}</span> |
| <span class="endpoint-summary">Serve training plot files</span> |
| <span class="expand-icon">▼</span> |
| </div> |
| <div class="endpoint-body"> |
| <p class="endpoint-desc">Serves files from the <code>/plots/</code> directory. The training results page fetches <code>training_metrics.json</code> for live chart data. Run <code>python fleet_train.py --simulate</code> to generate plot files.</p> |
| <div class="schema-label">Common files</div> |
| <div class="schema-block">training_metrics.json <span class="schema-comment">// reward + detection curves</span> |
| reward_curve.png <span class="schema-comment">// matplotlib chart</span> |
| detection_rate.png <span class="schema-comment">// detection improvement</span></div> |
| <div class="try-it-section"> |
| <div class="try-it-title">Try It</div> |
| <div class="try-row"> |
| <label>filename</label> |
| <input id="plot-file" type="text" value="training_metrics.json" /> |
| </div> |
| <button class="btn-try" onclick="sendPlot()">Send Request</button> |
| <div class="response-block" id="resp-plots"></div> |
| </div> |
| </div> |
| </div> |
|
|
| </main> |
| </div> |
|
|
| <script> |
| |
| document.getElementById('base-url').textContent = window.location.origin; |
| |
| function toggle(id) { |
| const card = document.getElementById(id); |
| card.classList.toggle('open'); |
| } |
| |
| async function sendRequest(method, path, body, respId) { |
| const el = document.getElementById(respId); |
| el.className = 'response-block visible'; |
| el.textContent = 'Sending…'; |
| try { |
| const opts = { method, headers: { 'Content-Type': 'application/json' } }; |
| if (body !== null) opts.body = JSON.stringify(body); |
| const resp = await fetch(path, opts); |
| const text = await resp.text(); |
| let parsed; |
| try { parsed = JSON.parse(text); } catch { parsed = text; } |
| const statusEl = `<span class="response-status ${resp.ok ? 'status-ok' : 'status-err'}">${resp.status} ${resp.statusText}</span>\n`; |
| el.innerHTML = statusEl + (typeof parsed === 'object' ? JSON.stringify(parsed, null, 2) : parsed); |
| el.className = `response-block visible ${resp.ok ? '' : 'err'}`; |
| } catch (e) { |
| el.textContent = 'Error: ' + e.message; |
| el.className = 'response-block visible err'; |
| } |
| } |
| |
| async function sendReset() { |
| const task = document.getElementById('reset-task').value; |
| const seed = parseInt(document.getElementById('reset-seed').value) || 42; |
| await sendRequest('POST', '/fleet/reset', { task_id: task, seed }, 'resp-reset'); |
| } |
| |
| async function sendStep() { |
| const action_type = document.getElementById('step-action').value; |
| const worker_id = document.getElementById('step-worker').value; |
| const reason = document.getElementById('step-reason').value || null; |
| await sendRequest('POST', '/fleet/step', { action_type, worker_id, reason }, 'resp-step'); |
| } |
| |
| async function sendRAG() { |
| const question = document.getElementById('rag-q').value; |
| await sendRequest('POST', '/rag/query', { question }, 'resp-rag'); |
| } |
| |
| async function sendPlot() { |
| const filename = document.getElementById('plot-file').value; |
| await sendRequest('GET', `/plots/${encodeURIComponent(filename)}`, null, 'resp-plots'); |
| } |
| </script> |
| </body> |
| </html> |
|
|