Spaces:
Paused
Paused
icebear0828 Claude Opus 4.6 commited on
Commit ·
debd0e1
1
Parent(s): 35ed5a4
ui: two-level tabs — protocol (OpenAI/Anthropic/Gemini) → language (Python/cURL/Node.js)
Browse filesRestructure Integration Examples into a 3x3 grid with protocol as the
top-level tab and language as the sub-level tab. Each combination gets
its own idiomatic code example using the native SDK for that protocol.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- public/dashboard.html +144 -75
public/dashboard.html
CHANGED
|
@@ -475,8 +475,32 @@
|
|
| 475 |
transition: background 0.2s;
|
| 476 |
}
|
| 477 |
.code-block .copy-code-btn:hover { background: rgba(255,255,255,0.2); }
|
| 478 |
-
.
|
| 479 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 480 |
|
| 481 |
/* Footer */
|
| 482 |
.footer {
|
|
@@ -581,33 +605,28 @@
|
|
| 581 |
<!-- Integration Examples -->
|
| 582 |
<div class="examples-card">
|
| 583 |
<h2 class="section-title">Integration Examples</h2>
|
| 584 |
-
<
|
| 585 |
-
|
| 586 |
-
<button class="tab" onclick="
|
| 587 |
-
<button class="tab" onclick="
|
| 588 |
-
<button class="tab" onclick="
|
| 589 |
-
<button class="tab" onclick="switchTab('gemini', this)">Gemini</button>
|
| 590 |
-
</div>
|
| 591 |
-
<div class="tab-content active" id="tab-python">
|
| 592 |
-
<div class="code-block" id="code-python">Loading...
|
| 593 |
-
<button class="copy-code-btn" onclick="copyCode('code-python')">⎘ Copy</button></div>
|
| 594 |
-
</div>
|
| 595 |
-
<div class="tab-content" id="tab-curl">
|
| 596 |
-
<div class="code-block" id="code-curl">Loading...
|
| 597 |
-
<button class="copy-code-btn" onclick="copyCode('code-curl')">⎘ Copy</button></div>
|
| 598 |
</div>
|
| 599 |
-
<
|
| 600 |
-
|
| 601 |
-
<button class="
|
| 602 |
-
|
| 603 |
-
|
| 604 |
-
<div class="code-block" id="code-anthropic">Loading...
|
| 605 |
-
<button class="copy-code-btn" onclick="copyCode('code-anthropic')">⎘ Copy</button></div>
|
| 606 |
-
</div>
|
| 607 |
-
<div class="tab-content" id="tab-gemini">
|
| 608 |
-
<div class="code-block" id="code-gemini">Loading...
|
| 609 |
-
<button class="copy-code-btn" onclick="copyCode('code-gemini')">⎘ Copy</button></div>
|
| 610 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 611 |
</div>
|
| 612 |
</div>
|
| 613 |
|
|
@@ -812,12 +831,19 @@
|
|
| 812 |
}
|
| 813 |
}
|
| 814 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 815 |
function updateCodeExamples() {
|
| 816 |
const baseUrl = escapeHtml(document.getElementById('baseUrl').value);
|
| 817 |
const apiKey = escapeHtml(document.getElementById('apiKey').value || 'any-string');
|
| 818 |
const model = escapeHtml(document.getElementById('defaultModel').value);
|
|
|
|
| 819 |
|
| 820 |
-
|
|
|
|
| 821 |
`from openai import OpenAI
|
| 822 |
|
| 823 |
client = OpenAI(
|
|
@@ -827,27 +853,20 @@ client = OpenAI(
|
|
| 827 |
|
| 828 |
response = client.chat.completions.create(
|
| 829 |
model="${model}",
|
| 830 |
-
messages=[
|
| 831 |
-
{"role": "user", "content": "Explain quantum computing in simple terms"}
|
| 832 |
-
],
|
| 833 |
)
|
|
|
|
| 834 |
|
| 835 |
-
|
| 836 |
-
<button class="copy-code-btn" onclick="copyCode('code-python')">⎘ Copy Code</button>`;
|
| 837 |
-
|
| 838 |
-
document.getElementById('code-curl').innerHTML =
|
| 839 |
`curl ${baseUrl}/chat/completions \\
|
| 840 |
-H "Content-Type: application/json" \\
|
| 841 |
-H "Authorization: Bearer ${apiKey}" \\
|
| 842 |
-d '{
|
| 843 |
"model": "${model}",
|
| 844 |
-
"messages": [
|
| 845 |
-
|
| 846 |
-
]
|
| 847 |
-
}'
|
| 848 |
-
<button class="copy-code-btn" onclick="copyCode('code-curl')">⎘ Copy Code</button>`;
|
| 849 |
|
| 850 |
-
|
| 851 |
`import OpenAI from "openai";
|
| 852 |
|
| 853 |
const client = new OpenAI({
|
|
@@ -857,56 +876,90 @@ const client = new OpenAI({
|
|
| 857 |
|
| 858 |
const stream = await client.chat.completions.create({
|
| 859 |
model: "${model}",
|
| 860 |
-
messages: [
|
| 861 |
-
{ role: "user", content: "Explain quantum computing in simple terms" },
|
| 862 |
-
],
|
| 863 |
stream: true,
|
| 864 |
});
|
| 865 |
-
|
| 866 |
for await (const chunk of stream) {
|
| 867 |
process.stdout.write(chunk.choices[0]?.delta?.content || "");
|
| 868 |
-
}
|
| 869 |
-
|
|
|
|
|
|
|
|
|
|
| 870 |
|
| 871 |
-
|
| 872 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 873 |
`import Anthropic from "@anthropic-ai/sdk";
|
| 874 |
|
| 875 |
const client = new Anthropic({
|
| 876 |
-
baseURL: "${
|
| 877 |
apiKey: "${apiKey}",
|
| 878 |
});
|
| 879 |
|
| 880 |
const message = await client.messages.create({
|
| 881 |
model: "claude-sonnet-4-20250514",
|
| 882 |
max_tokens: 1024,
|
| 883 |
-
messages: [
|
| 884 |
-
{ role: "user", content: "Explain quantum computing in simple terms" },
|
| 885 |
-
],
|
| 886 |
});
|
|
|
|
| 887 |
|
| 888 |
-
|
| 889 |
-
|
|
|
|
| 890 |
|
| 891 |
-
|
| 892 |
-
|
| 893 |
-
|
| 894 |
-
|
| 895 |
-
|
| 896 |
-
|
| 897 |
-
|
| 898 |
-
|
| 899 |
-
|
|
|
|
| 900 |
|
| 901 |
-
|
| 902 |
-
curl ${
|
| 903 |
-H "Content-Type: application/json" \\
|
| 904 |
-d '{
|
| 905 |
-
"contents": [
|
| 906 |
-
|
| 907 |
-
|
| 908 |
-
|
| 909 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 910 |
}
|
| 911 |
|
| 912 |
function saveOverrides() {
|
|
@@ -954,11 +1007,27 @@ curl ${geminiBase}/v1beta/models/gemini-2.5-pro:streamGenerateContent?alt=sse&ke
|
|
| 954 |
document.getElementById('defaultModel').addEventListener('change', () => { updateCodeExamples(); saveOverrides(); });
|
| 955 |
}
|
| 956 |
|
| 957 |
-
|
| 958 |
-
|
| 959 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 960 |
el.classList.add('active');
|
| 961 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 962 |
}
|
| 963 |
|
| 964 |
function copyField(id, btn) {
|
|
|
|
| 475 |
transition: background 0.2s;
|
| 476 |
}
|
| 477 |
.code-block .copy-code-btn:hover { background: rgba(255,255,255,0.2); }
|
| 478 |
+
.tabs-protocol {
|
| 479 |
+
margin-bottom: 0;
|
| 480 |
+
border-bottom: none;
|
| 481 |
+
}
|
| 482 |
+
.tabs-protocol .tab {
|
| 483 |
+
font-weight: 600;
|
| 484 |
+
font-size: 0.82rem;
|
| 485 |
+
}
|
| 486 |
+
.tabs-protocol .tab.active {
|
| 487 |
+
border-bottom-color: #10a37f;
|
| 488 |
+
}
|
| 489 |
+
.tabs-lang {
|
| 490 |
+
border-bottom: 1px solid #e5e7eb;
|
| 491 |
+
margin-bottom: 0.75rem;
|
| 492 |
+
}
|
| 493 |
+
.tabs-lang .tab {
|
| 494 |
+
font-size: 0.75rem;
|
| 495 |
+
padding: 5px 12px;
|
| 496 |
+
color: #9ca3af;
|
| 497 |
+
}
|
| 498 |
+
.tabs-lang .tab.active {
|
| 499 |
+
color: #111827;
|
| 500 |
+
border-bottom-color: #6b7280;
|
| 501 |
+
}
|
| 502 |
+
.code-panel { display: none; }
|
| 503 |
+
.code-panel.active { display: block; }
|
| 504 |
|
| 505 |
/* Footer */
|
| 506 |
.footer {
|
|
|
|
| 605 |
<!-- Integration Examples -->
|
| 606 |
<div class="examples-card">
|
| 607 |
<h2 class="section-title">Integration Examples</h2>
|
| 608 |
+
<!-- Protocol tabs (top level) -->
|
| 609 |
+
<div class="tabs tabs-protocol">
|
| 610 |
+
<button class="tab active" onclick="switchProtocol('openai', this)">OpenAI</button>
|
| 611 |
+
<button class="tab" onclick="switchProtocol('anthropic', this)">Anthropic</button>
|
| 612 |
+
<button class="tab" onclick="switchProtocol('gemini', this)">Gemini</button>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 613 |
</div>
|
| 614 |
+
<!-- Language tabs (sub level) -->
|
| 615 |
+
<div class="tabs tabs-lang">
|
| 616 |
+
<button class="tab active" data-lang="python" onclick="switchLang('python', this)">Python</button>
|
| 617 |
+
<button class="tab" data-lang="curl" onclick="switchLang('curl', this)">cURL</button>
|
| 618 |
+
<button class="tab" data-lang="node" onclick="switchLang('node', this)">Node.js</button>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 619 |
</div>
|
| 620 |
+
<!-- Code panels: {protocol}-{lang} -->
|
| 621 |
+
<div class="code-panel active" id="panel-openai-python"><div class="code-block" id="code-openai-python">Loading...<button class="copy-code-btn" onclick="copyCode('code-openai-python')">⎘ Copy</button></div></div>
|
| 622 |
+
<div class="code-panel" id="panel-openai-curl"><div class="code-block" id="code-openai-curl">Loading...<button class="copy-code-btn" onclick="copyCode('code-openai-curl')">⎘ Copy</button></div></div>
|
| 623 |
+
<div class="code-panel" id="panel-openai-node"><div class="code-block" id="code-openai-node">Loading...<button class="copy-code-btn" onclick="copyCode('code-openai-node')">⎘ Copy</button></div></div>
|
| 624 |
+
<div class="code-panel" id="panel-anthropic-python"><div class="code-block" id="code-anthropic-python">Loading...<button class="copy-code-btn" onclick="copyCode('code-anthropic-python')">⎘ Copy</button></div></div>
|
| 625 |
+
<div class="code-panel" id="panel-anthropic-curl"><div class="code-block" id="code-anthropic-curl">Loading...<button class="copy-code-btn" onclick="copyCode('code-anthropic-curl')">⎘ Copy</button></div></div>
|
| 626 |
+
<div class="code-panel" id="panel-anthropic-node"><div class="code-block" id="code-anthropic-node">Loading...<button class="copy-code-btn" onclick="copyCode('code-anthropic-node')">⎘ Copy</button></div></div>
|
| 627 |
+
<div class="code-panel" id="panel-gemini-python"><div class="code-block" id="code-gemini-python">Loading...<button class="copy-code-btn" onclick="copyCode('code-gemini-python')">⎘ Copy</button></div></div>
|
| 628 |
+
<div class="code-panel" id="panel-gemini-curl"><div class="code-block" id="code-gemini-curl">Loading...<button class="copy-code-btn" onclick="copyCode('code-gemini-curl')">⎘ Copy</button></div></div>
|
| 629 |
+
<div class="code-panel" id="panel-gemini-node"><div class="code-block" id="code-gemini-node">Loading...<button class="copy-code-btn" onclick="copyCode('code-gemini-node')">⎘ Copy</button></div></div>
|
| 630 |
</div>
|
| 631 |
</div>
|
| 632 |
|
|
|
|
| 831 |
}
|
| 832 |
}
|
| 833 |
|
| 834 |
+
function setCode(id, code) {
|
| 835 |
+
const el = document.getElementById(id);
|
| 836 |
+
if (el) el.innerHTML = code + `\n<button class="copy-code-btn" onclick="copyCode('${id}')">⎘ Copy</button>`;
|
| 837 |
+
}
|
| 838 |
+
|
| 839 |
function updateCodeExamples() {
|
| 840 |
const baseUrl = escapeHtml(document.getElementById('baseUrl').value);
|
| 841 |
const apiKey = escapeHtml(document.getElementById('apiKey').value || 'any-string');
|
| 842 |
const model = escapeHtml(document.getElementById('defaultModel').value);
|
| 843 |
+
const origin = escapeHtml(window.location.origin);
|
| 844 |
|
| 845 |
+
// ── OpenAI ──
|
| 846 |
+
setCode('code-openai-python',
|
| 847 |
`from openai import OpenAI
|
| 848 |
|
| 849 |
client = OpenAI(
|
|
|
|
| 853 |
|
| 854 |
response = client.chat.completions.create(
|
| 855 |
model="${model}",
|
| 856 |
+
messages=[{"role": "user", "content": "Hello"}],
|
|
|
|
|
|
|
| 857 |
)
|
| 858 |
+
print(response.choices[0].message.content)`);
|
| 859 |
|
| 860 |
+
setCode('code-openai-curl',
|
|
|
|
|
|
|
|
|
|
| 861 |
`curl ${baseUrl}/chat/completions \\
|
| 862 |
-H "Content-Type: application/json" \\
|
| 863 |
-H "Authorization: Bearer ${apiKey}" \\
|
| 864 |
-d '{
|
| 865 |
"model": "${model}",
|
| 866 |
+
"messages": [{"role": "user", "content": "Hello"}]
|
| 867 |
+
}'`);
|
|
|
|
|
|
|
|
|
|
| 868 |
|
| 869 |
+
setCode('code-openai-node',
|
| 870 |
`import OpenAI from "openai";
|
| 871 |
|
| 872 |
const client = new OpenAI({
|
|
|
|
| 876 |
|
| 877 |
const stream = await client.chat.completions.create({
|
| 878 |
model: "${model}",
|
| 879 |
+
messages: [{ role: "user", content: "Hello" }],
|
|
|
|
|
|
|
| 880 |
stream: true,
|
| 881 |
});
|
|
|
|
| 882 |
for await (const chunk of stream) {
|
| 883 |
process.stdout.write(chunk.choices[0]?.delta?.content || "");
|
| 884 |
+
}`);
|
| 885 |
+
|
| 886 |
+
// ── Anthropic ──
|
| 887 |
+
setCode('code-anthropic-python',
|
| 888 |
+
`import anthropic
|
| 889 |
|
| 890 |
+
client = anthropic.Anthropic(
|
| 891 |
+
base_url="${origin}/v1",
|
| 892 |
+
api_key="${apiKey}",
|
| 893 |
+
)
|
| 894 |
+
|
| 895 |
+
message = client.messages.create(
|
| 896 |
+
model="claude-sonnet-4-20250514",
|
| 897 |
+
max_tokens=1024,
|
| 898 |
+
messages=[{"role": "user", "content": "Hello"}],
|
| 899 |
+
)
|
| 900 |
+
print(message.content[0].text)`);
|
| 901 |
+
|
| 902 |
+
setCode('code-anthropic-curl',
|
| 903 |
+
`curl ${origin}/v1/messages \\
|
| 904 |
+
-H "Content-Type: application/json" \\
|
| 905 |
+
-H "x-api-key: ${apiKey}" \\
|
| 906 |
+
-H "anthropic-version: 2023-06-01" \\
|
| 907 |
+
-d '{
|
| 908 |
+
"model": "claude-sonnet-4-20250514",
|
| 909 |
+
"max_tokens": 1024,
|
| 910 |
+
"messages": [{"role": "user", "content": "Hello"}]
|
| 911 |
+
}'`);
|
| 912 |
+
|
| 913 |
+
setCode('code-anthropic-node',
|
| 914 |
`import Anthropic from "@anthropic-ai/sdk";
|
| 915 |
|
| 916 |
const client = new Anthropic({
|
| 917 |
+
baseURL: "${origin}/v1",
|
| 918 |
apiKey: "${apiKey}",
|
| 919 |
});
|
| 920 |
|
| 921 |
const message = await client.messages.create({
|
| 922 |
model: "claude-sonnet-4-20250514",
|
| 923 |
max_tokens: 1024,
|
| 924 |
+
messages: [{ role: "user", content: "Hello" }],
|
|
|
|
|
|
|
| 925 |
});
|
| 926 |
+
console.log(message.content[0].text);`);
|
| 927 |
|
| 928 |
+
// ── Gemini ──
|
| 929 |
+
setCode('code-gemini-python',
|
| 930 |
+
`from google import genai
|
| 931 |
|
| 932 |
+
client = genai.Client(
|
| 933 |
+
api_key="${apiKey}",
|
| 934 |
+
http_options={"base_url": "${origin}/v1beta"},
|
| 935 |
+
)
|
| 936 |
+
|
| 937 |
+
response = client.models.generate_content(
|
| 938 |
+
model="gemini-2.5-pro",
|
| 939 |
+
contents="Hello",
|
| 940 |
+
)
|
| 941 |
+
print(response.text)`);
|
| 942 |
|
| 943 |
+
setCode('code-gemini-curl',
|
| 944 |
+
`curl "${origin}/v1beta/models/gemini-2.5-pro:generateContent?key=${apiKey}" \\
|
| 945 |
-H "Content-Type: application/json" \\
|
| 946 |
-d '{
|
| 947 |
+
"contents": [{"role": "user", "parts": [{"text": "Hello"}]}]
|
| 948 |
+
}'`);
|
| 949 |
+
|
| 950 |
+
setCode('code-gemini-node',
|
| 951 |
+
`import { GoogleGenAI } from "@google/genai";
|
| 952 |
+
|
| 953 |
+
const ai = new GoogleGenAI({
|
| 954 |
+
apiKey: "${apiKey}",
|
| 955 |
+
httpOptions: { baseUrl: "${origin}/v1beta" },
|
| 956 |
+
});
|
| 957 |
+
|
| 958 |
+
const response = await ai.models.generateContent({
|
| 959 |
+
model: "gemini-2.5-pro",
|
| 960 |
+
contents: "Hello",
|
| 961 |
+
});
|
| 962 |
+
console.log(response.text);`);
|
| 963 |
}
|
| 964 |
|
| 965 |
function saveOverrides() {
|
|
|
|
| 1007 |
document.getElementById('defaultModel').addEventListener('change', () => { updateCodeExamples(); saveOverrides(); });
|
| 1008 |
}
|
| 1009 |
|
| 1010 |
+
let currentProtocol = 'openai';
|
| 1011 |
+
let currentLang = 'python';
|
| 1012 |
+
|
| 1013 |
+
function switchProtocol(proto, el) {
|
| 1014 |
+
currentProtocol = proto;
|
| 1015 |
+
document.querySelectorAll('.tabs-protocol .tab').forEach(t => t.classList.remove('active'));
|
| 1016 |
+
el.classList.add('active');
|
| 1017 |
+
showActivePanel();
|
| 1018 |
+
}
|
| 1019 |
+
|
| 1020 |
+
function switchLang(lang, el) {
|
| 1021 |
+
currentLang = lang;
|
| 1022 |
+
document.querySelectorAll('.tabs-lang .tab').forEach(t => t.classList.remove('active'));
|
| 1023 |
el.classList.add('active');
|
| 1024 |
+
showActivePanel();
|
| 1025 |
+
}
|
| 1026 |
+
|
| 1027 |
+
function showActivePanel() {
|
| 1028 |
+
document.querySelectorAll('.code-panel').forEach(p => p.classList.remove('active'));
|
| 1029 |
+
const panel = document.getElementById('panel-' + currentProtocol + '-' + currentLang);
|
| 1030 |
+
if (panel) panel.classList.add('active');
|
| 1031 |
}
|
| 1032 |
|
| 1033 |
function copyField(id, btn) {
|