Skip to content

Commit 0f8e490

Browse files
committed
update.
1 parent daabc85 commit 0f8e490

12 files changed

Lines changed: 88 additions & 540 deletions

File tree

docs/usermanual.md

Lines changed: 0 additions & 508 deletions
This file was deleted.

homepage/index.html

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<!doctype html>
2+
<html lang="en" class="dark">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>Tingly Box - Provider-Agnostic AI Model Proxy</title>
7+
<meta name="description" content="Tingly Box is a provider-agnostic AI model proxy with a unified OpenAI-compatible API, config-based request forwarding, and web management UI." />
8+
<meta name="author" content="Tingly Box" />
9+
<meta name="keywords" content="AI, LLM, proxy, OpenAI, API, model, provider, unified" />
10+
11+
<meta property="og:title" content="Tingly Box - Provider-Agnostic AI Model Proxy" />
12+
<meta property="og:description" content="Unified OpenAI-compatible API for multiple AI providers with config-based request forwarding and web management UI." />
13+
<meta property="og:type" content="website" />
14+
15+
<meta name="twitter:card" content="summary_large_image" />
16+
<meta name="twitter:title" content="Tingly Box - Provider-Agnostic AI Model Proxy" />
17+
<meta name="twitter:description" content="Unified OpenAI-compatible API for multiple AI providers." />
18+
19+
<link rel="canonical" href="https://tingly-dev.github.io/" />
20+
</head>
21+
22+
<body>
23+
<div id="root"></div>
24+
<script type="module" src="/src/main.tsx"></script>
25+
</body>
26+
</html>

src/App.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const App = () => (
1515
<TooltipProvider>
1616
<Toaster />
1717
<Sonner />
18-
<BrowserRouter>
18+
<BrowserRouter basename={import.meta.env.PROD ? "/tingly-box" : "/"}>
1919
<Routes>
2020
<Route path="/" element={<Index />} />
2121
{/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL "*" ROUTE */}

src/assets/ChooseProvider.png

-61.2 KB
Binary file not shown.

src/assets/Credential.png

-302 KB
Binary file not shown.

src/assets/Home.png

-417 KB
Binary file not shown.

src/assets/ProviderAdd.png

-110 KB
Binary file not shown.

src/assets/Routing.png

-384 KB
Binary file not shown.

src/data/code.tsx

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@ import SyntaxHighlighter from 'react-syntax-highlighter/dist/esm/prism-light';
1010
import {oneDark} from 'react-syntax-highlighter/dist/esm/styles/prism';
1111
import {Info, Sparkles, Settings2, MousePointerClick, RefreshCw} from 'lucide-react';
1212

13-
import screenshotProviderAdd from "@/assets/ProviderAdd.png";
14-
import screenshotChooseProvider from "@/assets/ChooseProvider.png";
13+
// External image URLs from GitHub repository
14+
const screenshotBaseUrl = "https://raw.githubusercontent.com/tingly-dev/tingly-box/refs/heads/main/docs/images";
15+
const screenshotProviderAdd = `${screenshotBaseUrl}/2-openai.png`;
16+
const screenshotChooseProvider = `${screenshotBaseUrl}/4-select.png`;
1517

1618
import {componentStyles} from "@/theme";
1719

@@ -165,19 +167,45 @@ export const STEPS = [
165167
<div className="space-y-4">
166168
<div className="space-y-2">
167169
<p className={`${componentStyles.sectionHeader} ${componentStyles.sectionHeaderMuted}`}>Python
168-
SDK</p>
170+
SDK (OpenAI)</p>
169171
<CodeBlock
170172
language="python"
171-
code={`import openai\n\nclient = openai.OpenAI(\n base_url = "http://localhost:12580/openai",\n api_key = "YOUR_TINGLY_BOX_KEY"\n)\n\n# Use as before\nresponse = client.chat.completions.create(\n model = "tingly",\n messages = [{"role": "user", "content": "Hello!"}]\n)`}
173+
code={`from openai import OpenAI
174+
175+
client = OpenAI(
176+
api_key="your-tingly-model-token",
177+
base_url="http://localhost:12580/tingly/openai/v1"
178+
)
179+
180+
response = client.chat.completions.create(
181+
# To pass litellm model name validation, use "gpt-3.5-turbo"
182+
model="tingly",
183+
messages=[{"role": "user", "content": "Hello!"}]
184+
)
185+
print(response)`}
172186
/>
173187
</div>
174188
<div className="space-y-2">
175189
<p className={`${componentStyles.sectionHeader} ${componentStyles.sectionHeaderMuted}`}>
176-
Claude Settings (~/.claude/settings.json)
190+
Claude Code Settings (~/.claude/settings.json)
177191
</p>
178192
<CodeBlock
179193
language="json"
180-
code={`{\n "env": {\n "ANTHROPIC_AUTH_TOKEN": "{tingly-box-token}",\n "ANTHROPIC_BASE_URL": "http://localhost:12580/anthropic",\n "ANTHROPIC_MODEL": "tingly"\n }\n}`}
194+
code={`{
195+
"env": {
196+
"DISABLE_TELEMETRY": "1",
197+
"DISABLE_ERROR_REPORTING": "1",
198+
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1",
199+
"API_TIMEOUT_MS": "3000000",
200+
"ANTHROPIC_AUTH_TOKEN": "{content after tingly token cmd 'Current API Key from Global Config'}",
201+
"ANTHROPIC_BASE_URL": "http://localhost:12580/tingly/claude_code",
202+
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "tingly/cc",
203+
"ANTHROPIC_DEFAULT_OPUS_MODEL": "tingly/cc",
204+
"ANTHROPIC_DEFAULT_SONNET_MODEL": "tingly/cc",
205+
"ANTHROPIC_MODEL": "tingly/cc",
206+
"hasCompletedOnboarding": true
207+
}
208+
}`}
181209
/>
182210
</div>
183211
</div>

src/data/text.ts

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,35 @@
1+
import { ArrowLeftRight, Gauge, Globe, Layers, Zap, Shield, LayoutDashboard, BarChart3 } from "lucide-react";
12

2-
3-
import screenshotHome from "@/assets/Home.png";
4-
import screenshotCredentials from "@/assets/Credential.png";
5-
import screenshotRules from "@/assets/Routing.png";
6-
import { ArrowLeftRight, Gauge, Globe, Layers } from "lucide-react";
3+
// External image URLs from GitHub repository
4+
const screenshotBaseUrl = "https://raw.githubusercontent.com/tingly-dev/tingly-box/refs/heads/main/docs/images";
75

86
export const screenshots = [
9-
{ src: screenshotHome, alt: "Tingly Box Home - Model Proxy Config" },
10-
{ src: screenshotCredentials, alt: "Tingly Box Credentials Management" },
11-
{ src: screenshotRules, alt: "Tingly Box Proxy Rules Configuration" },
12-
// { src: screenshotSystem, alt: "Tingly Box Server Status & Control" },
13-
// { src: screenshotHistory, alt: "Tingly Box Activity Log & History" },
7+
{ src: `${screenshotBaseUrl}/1-home.png`, alt: "Tingly Box Home - Model Proxy Config" },
8+
{ src: `${screenshotBaseUrl}/2-openai.png`, alt: "Tingly Box Credentials Management" },
9+
{ src: `${screenshotBaseUrl}/4-select.png`, alt: "Tingly Box Proxy Rules Configuration" },
10+
// { src: `${screenshotBaseUrl}/xxx.png`, alt: "Tingly Box Server Status & Control" },
11+
// { src: `${screenshotBaseUrl}/xxx.png`, alt: "Tingly Box Activity Log & History" },
1412
];
1513

1614
export const features = [
17-
{ icon: Globe, title: "Unified API", description: "Single configuration to connect hundreds of model providers." },
18-
{ icon: Layers, title: "Load Balancing", description: "Distribute requests across multiple tokens by tactics." },
19-
{
20-
icon: ArrowLeftRight,
21-
title: "Auto API Translation",
22-
description: "Automatically translate API parameters among different providers."
23-
},
24-
{ icon: Gauge, title: "High Performance", description: "Additional latency less than 1ms for seamless integration." },
15+
{ icon: Globe, title: "Unified API", description: "One mixin endpoint to rule them all — use OpenAI, Anthropic, or Google APIs interchangeably." },
16+
{ icon: Zap, title: "Smart Routing", description: "Intelligently route requests across models and tokens based on cost, speed, or custom policies — not just simple load balancing." },
17+
{ icon: Layers, title: "Smart Context Compression", description: "(Coming soon) Automatically distill context to its essential parts for sharper relevance, lower cost, and faster responses." },
18+
{ icon: ArrowLeftRight, title: "Auto API Translation", description: "Seamlessly bridge OpenAI, Anthropic, Google, and other API dialects — no code changes needed." },
19+
{ icon: Gauge, title: "Blazing Fast", description: "Adds typically < 1ms of overhead — so you get flexibility without latency tax." },
20+
{ icon: Shield, title: "Flexible Auth", description: "Support for both API keys and OAuth (e.g., Claude.ai) — use your existing quotas anywhere." },
21+
{ icon: LayoutDashboard, title: "Visual Control Panel", description: "Intuitive UI to manage providers, routes, aliases, and models at a glance." },
22+
{ icon: BarChart3, title: "Client Side Usage Stats", description: "Track token consumption, latency, cost estimates, and model selection per request — directly from your client." },
2523
];
2624

2725
export const faqs = [
2826
{
29-
question: "How does load balancing work?",
30-
answer: "Tingly Box automatically distributes requests across multiple API tokens using routing strategies. By default, it uses round-robin with a request threshold of 100 (if not configured)."
27+
question: "How does smart routing work?",
28+
answer: "Tingly Box intelligently routes requests across multiple API tokens and models using configurable strategies. Unlike simple load balancing, it considers cost, speed, and custom policies to optimize each request. By default, it uses round-robin with a request threshold of 100 (if not configured)."
29+
},
30+
{
31+
question: "Can I use OAuth providers like Claude Code?",
32+
answer: "Yes! You can add OAuth providers (like Claude Code) through the Web UI at http://localhost:12580. Once configured, requests route through your OAuth-authorized provider, using your existing quota instead of requiring a separate API key. This works with any OpenAI-compatible tool."
3133
},
3234
{
3335
question: "How do I enable mirrored networking mode in WSL2?",
@@ -39,6 +41,6 @@ export const faqs = [
3941
},
4042
{
4143
question: "Why do I get \"BadRequestError: LLM Provider NOT provided\" when using LiteLLM with model set to \"tingly\"?",
42-
answer: "LiteLLM validates the model name and expects it to be a known, supported model. When you set the model name to \"tingly\", LiteLLM treats it as invalid and throws this error. To work around this, configure the local model name as a real model such as \"gpt-3.5-turbo\". This is only to pass LiteLLMs validation—the actual remote model used by tingly-box does not change."
44+
answer: "LiteLLM validates the model name and expects it to be a known, supported model. When you set the model name to \"tingly\", LiteLLM treats it as invalid and throws this error. To work around this, configure the local model name as a real model such as \"gpt-3.5-turbo\". This is only to pass LiteLLM's validation—the actual remote model used by tingly-box does not change."
4345
}
4446
];

0 commit comments

Comments
 (0)