aigetwey 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +84 -0
- package/LICENSE +21 -0
- package/README.md +302 -0
- package/assets/logo.svg +8 -0
- package/assets/screenshot.png +0 -0
- package/assets/wordmark.svg +9 -0
- package/config.example.yaml +56 -0
- package/dashboard/.env.example +12 -0
- package/dashboard/next-env.d.ts +6 -0
- package/dashboard/next.config.ts +12 -0
- package/dashboard/package-lock.json +1771 -0
- package/dashboard/package.json +29 -0
- package/dashboard/postcss.config.mjs +5 -0
- package/dashboard/src/app/(console)/combos/page.tsx +10 -0
- package/dashboard/src/app/(console)/config/page.tsx +5 -0
- package/dashboard/src/app/(console)/console/page.tsx +92 -0
- package/dashboard/src/app/(console)/endpoint/page.tsx +5 -0
- package/dashboard/src/app/(console)/layout.tsx +17 -0
- package/dashboard/src/app/(console)/page.tsx +8 -0
- package/dashboard/src/app/(console)/providers/[id]/page.tsx +6 -0
- package/dashboard/src/app/(console)/providers/page.tsx +5 -0
- package/dashboard/src/app/(console)/quota/page.tsx +5 -0
- package/dashboard/src/app/(console)/tools/[id]/page.tsx +6 -0
- package/dashboard/src/app/(console)/tools/page.tsx +5 -0
- package/dashboard/src/app/(console)/usage/page.tsx +24 -0
- package/dashboard/src/app/api/cli-detect/[tool]/route.ts +253 -0
- package/dashboard/src/app/api/gw/[...path]/route.ts +89 -0
- package/dashboard/src/app/api/login/route.ts +30 -0
- package/dashboard/src/app/api/logout/route.ts +9 -0
- package/dashboard/src/app/api/password/route.ts +34 -0
- package/dashboard/src/app/globals.css +340 -0
- package/dashboard/src/app/icon.svg +8 -0
- package/dashboard/src/app/layout.tsx +28 -0
- package/dashboard/src/app/login/page.tsx +60 -0
- package/dashboard/src/components/AreaChart.tsx +115 -0
- package/dashboard/src/components/Badge.tsx +32 -0
- package/dashboard/src/components/Button.tsx +60 -0
- package/dashboard/src/components/CapacityBadges.tsx +40 -0
- package/dashboard/src/components/Checkbox.tsx +40 -0
- package/dashboard/src/components/CliToolConfig.tsx +63 -0
- package/dashboard/src/components/ConfigEditor.tsx +199 -0
- package/dashboard/src/components/ConfirmModal.tsx +36 -0
- package/dashboard/src/components/CooldownTimer.tsx +42 -0
- package/dashboard/src/components/EndpointView.tsx +439 -0
- package/dashboard/src/components/Icon.tsx +25 -0
- package/dashboard/src/components/KeyReveal.tsx +78 -0
- package/dashboard/src/components/Lamp.tsx +8 -0
- package/dashboard/src/components/LogTable.tsx +223 -0
- package/dashboard/src/components/LogoutButton.tsx +20 -0
- package/dashboard/src/components/ModelPicker.tsx +121 -0
- package/dashboard/src/components/ModelSelectModal.tsx +126 -0
- package/dashboard/src/components/PasswordEditor.tsx +86 -0
- package/dashboard/src/components/PricingEditor.tsx +171 -0
- package/dashboard/src/components/ProviderDetail.tsx +566 -0
- package/dashboard/src/components/ProviderManager.tsx +311 -0
- package/dashboard/src/components/QuotaView.tsx +78 -0
- package/dashboard/src/components/Rail.tsx +82 -0
- package/dashboard/src/components/RichCard.tsx +46 -0
- package/dashboard/src/components/RoutingView.tsx +329 -0
- package/dashboard/src/components/ThemeProvider.tsx +36 -0
- package/dashboard/src/components/ToastProvider.tsx +58 -0
- package/dashboard/src/components/ToolDetail.tsx +475 -0
- package/dashboard/src/components/TopBar.tsx +128 -0
- package/dashboard/src/components/UsageView.tsx +151 -0
- package/dashboard/src/components/ui.tsx +54 -0
- package/dashboard/src/lib/capabilities.ts +318 -0
- package/dashboard/src/lib/cliTools.ts +120 -0
- package/dashboard/src/lib/client.ts +190 -0
- package/dashboard/src/lib/gateway.ts +269 -0
- package/dashboard/src/lib/session.ts +71 -0
- package/dashboard/src/middleware.ts +37 -0
- package/dashboard/tsconfig.json +21 -0
- package/dist/adapters/anthropic.js +289 -0
- package/dist/adapters/anthropic.js.map +1 -0
- package/dist/adapters/gemini.js +268 -0
- package/dist/adapters/gemini.js.map +1 -0
- package/dist/adapters/index.js +8 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/openai.js +13 -0
- package/dist/adapters/openai.js.map +1 -0
- package/dist/cli/tray/autostart.js +152 -0
- package/dist/cli/tray/autostart.js.map +1 -0
- package/dist/cli/tray/icon.js +4 -0
- package/dist/cli/tray/icon.js.map +1 -0
- package/dist/cli/tray/tray.js +141 -0
- package/dist/cli/tray/tray.js.map +1 -0
- package/dist/cli/tray/trayRuntime.js +91 -0
- package/dist/cli/tray/trayRuntime.js.map +1 -0
- package/dist/cli.js +361 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.js +728 -0
- package/dist/config.js.map +1 -0
- package/dist/core/authStore.js +78 -0
- package/dist/core/authStore.js.map +1 -0
- package/dist/core/canonical.js +9 -0
- package/dist/core/canonical.js.map +1 -0
- package/dist/core/console-buffer.js +25 -0
- package/dist/core/console-buffer.js.map +1 -0
- package/dist/core/fallback.js +62 -0
- package/dist/core/fallback.js.map +1 -0
- package/dist/core/handler.js +174 -0
- package/dist/core/handler.js.map +1 -0
- package/dist/core/keypool.js +105 -0
- package/dist/core/keypool.js.map +1 -0
- package/dist/core/quota.js +165 -0
- package/dist/core/quota.js.map +1 -0
- package/dist/core/state.js +52 -0
- package/dist/core/state.js.map +1 -0
- package/dist/db.js +193 -0
- package/dist/db.js.map +1 -0
- package/dist/headroom/compress.js +44 -0
- package/dist/headroom/compress.js.map +1 -0
- package/dist/headroom/detect.js +108 -0
- package/dist/headroom/detect.js.map +1 -0
- package/dist/headroom/process.js +158 -0
- package/dist/headroom/process.js.map +1 -0
- package/dist/inject/caveman.js +30 -0
- package/dist/inject/caveman.js.map +1 -0
- package/dist/inject/index.js +24 -0
- package/dist/inject/index.js.map +1 -0
- package/dist/inject/ponytail.js +19 -0
- package/dist/inject/ponytail.js.map +1 -0
- package/dist/middleware/auth.js +66 -0
- package/dist/middleware/auth.js.map +1 -0
- package/dist/providers/capabilities.js +246 -0
- package/dist/providers/capabilities.js.map +1 -0
- package/dist/providers/free.js +43 -0
- package/dist/providers/free.js.map +1 -0
- package/dist/providers/pricing.js +224 -0
- package/dist/providers/pricing.js.map +1 -0
- package/dist/providers/vertex.js +97 -0
- package/dist/providers/vertex.js.map +1 -0
- package/dist/routes/admin.js +622 -0
- package/dist/routes/admin.js.map +1 -0
- package/dist/routes/health.js +4 -0
- package/dist/routes/health.js.map +1 -0
- package/dist/routes/index.js +12 -0
- package/dist/routes/index.js.map +1 -0
- package/dist/routes/v1.js +75 -0
- package/dist/routes/v1.js.map +1 -0
- package/dist/rtk/detect.js +50 -0
- package/dist/rtk/detect.js.map +1 -0
- package/dist/rtk/filters.js +85 -0
- package/dist/rtk/filters.js.map +1 -0
- package/dist/rtk/index.js +39 -0
- package/dist/rtk/index.js.map +1 -0
- package/dist/server.js +100 -0
- package/dist/server.js.map +1 -0
- package/dist/stream/anthropic-stream.js +239 -0
- package/dist/stream/anthropic-stream.js.map +1 -0
- package/dist/stream/chunk.js +7 -0
- package/dist/stream/chunk.js.map +1 -0
- package/dist/stream/gemini-stream.js +135 -0
- package/dist/stream/gemini-stream.js.map +1 -0
- package/dist/stream/index.js +12 -0
- package/dist/stream/index.js.map +1 -0
- package/dist/stream/openai-stream.js +34 -0
- package/dist/stream/openai-stream.js.map +1 -0
- package/dist/stream/sse.js +64 -0
- package/dist/stream/sse.js.map +1 -0
- package/dist/translator/thinking.js +70 -0
- package/dist/translator/thinking.js.map +1 -0
- package/dist/translator/thinkingUnified.js +322 -0
- package/dist/translator/thinkingUnified.js.map +1 -0
- package/dist/upstream/client.js +120 -0
- package/dist/upstream/client.js.map +1 -0
- package/package.json +76 -0
- package/run.sh +27 -0
- package/src/adapters/anthropic.ts +377 -0
- package/src/adapters/gemini.ts +341 -0
- package/src/adapters/index.ts +17 -0
- package/src/adapters/openai.ts +22 -0
- package/src/cli/tray/autostart.ts +133 -0
- package/src/cli/tray/icon.ts +4 -0
- package/src/cli/tray/tray.ts +156 -0
- package/src/cli/tray/trayRuntime.ts +90 -0
- package/src/cli.ts +379 -0
- package/src/config.ts +777 -0
- package/src/core/authStore.ts +86 -0
- package/src/core/canonical.ts +93 -0
- package/src/core/console-buffer.ts +39 -0
- package/src/core/fallback.ts +116 -0
- package/src/core/handler.ts +236 -0
- package/src/core/keypool.ts +152 -0
- package/src/core/quota.ts +214 -0
- package/src/core/state.ts +65 -0
- package/src/db.ts +280 -0
- package/src/headroom/compress.ts +78 -0
- package/src/headroom/detect.ts +119 -0
- package/src/headroom/process.ts +166 -0
- package/src/inject/caveman.ts +35 -0
- package/src/inject/index.ts +46 -0
- package/src/inject/ponytail.ts +31 -0
- package/src/middleware/auth.ts +76 -0
- package/src/providers/capabilities.ts +297 -0
- package/src/providers/free.ts +53 -0
- package/src/providers/pricing.ts +261 -0
- package/src/providers/vertex.ts +117 -0
- package/src/routes/admin.ts +716 -0
- package/src/routes/health.ts +5 -0
- package/src/routes/index.ts +24 -0
- package/src/routes/v1.ts +87 -0
- package/src/rtk/detect.ts +55 -0
- package/src/rtk/filters.ts +94 -0
- package/src/rtk/index.ts +58 -0
- package/src/server.ts +108 -0
- package/src/stream/anthropic-stream.ts +310 -0
- package/src/stream/chunk.ts +46 -0
- package/src/stream/gemini-stream.ts +158 -0
- package/src/stream/index.ts +23 -0
- package/src/stream/openai-stream.ts +41 -0
- package/src/stream/sse.ts +72 -0
- package/src/translator/thinking.ts +64 -0
- package/src/translator/thinkingUnified.ts +319 -0
- package/src/upstream/client.ts +155 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useEffect, useState, useCallback } from "react";
|
|
4
|
+
import { adminApi } from "@/lib/client";
|
|
5
|
+
import { CardTitle } from "@/components/RichCard";
|
|
6
|
+
import { Icon } from "@/components/Icon";
|
|
7
|
+
import { Empty } from "@/components/ui";
|
|
8
|
+
import type { PricingPayload, PricingModel } from "@/lib/gateway";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Per-model price override editor (aigetwey's Pricing settings, adapted). Each model
|
|
12
|
+
* shows the auto-resolved default from the pricing table; typing an override stores
|
|
13
|
+
* it in config, and "use default" clears it. All rates are $/1M tokens.
|
|
14
|
+
*/
|
|
15
|
+
export function PricingEditor() {
|
|
16
|
+
const [data, setData] = useState<PricingPayload | null>(null);
|
|
17
|
+
const [error, setError] = useState("");
|
|
18
|
+
const [busy, setBusy] = useState("");
|
|
19
|
+
const [edits, setEdits] = useState<Record<string, { in: string; out: string }>>({});
|
|
20
|
+
|
|
21
|
+
const load = useCallback(async () => {
|
|
22
|
+
const r = await adminApi.pricing();
|
|
23
|
+
if (r.ok && r.data) {
|
|
24
|
+
setData(r.data);
|
|
25
|
+
setError("");
|
|
26
|
+
} else setError(r.error ?? "could not load pricing");
|
|
27
|
+
}, []);
|
|
28
|
+
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
void load();
|
|
31
|
+
}, [load]);
|
|
32
|
+
|
|
33
|
+
function keyOf(pid: string, mid: string) {
|
|
34
|
+
return `${pid}/${mid}`;
|
|
35
|
+
}
|
|
36
|
+
function field(pid: string, m: PricingModel, side: "in" | "out"): string {
|
|
37
|
+
const k = keyOf(pid, m.id);
|
|
38
|
+
if (edits[k]?.[side] !== undefined) return edits[k]![side];
|
|
39
|
+
const v = side === "in" ? m.price_in : m.price_out;
|
|
40
|
+
return v == null ? "" : String(v);
|
|
41
|
+
}
|
|
42
|
+
function setField(pid: string, mid: string, side: "in" | "out", val: string) {
|
|
43
|
+
const k = keyOf(pid, mid);
|
|
44
|
+
setEdits((e) => ({ ...e, [k]: { in: e[k]?.in ?? "", out: e[k]?.out ?? "", [side]: val } }));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function save(pid: string, m: PricingModel) {
|
|
48
|
+
const k = keyOf(pid, m.id);
|
|
49
|
+
setBusy(k);
|
|
50
|
+
const rawIn = field(pid, m, "in").trim();
|
|
51
|
+
const rawOut = field(pid, m, "out").trim();
|
|
52
|
+
const price_in = rawIn === "" ? null : Number(rawIn);
|
|
53
|
+
const price_out = rawOut === "" ? null : Number(rawOut);
|
|
54
|
+
const r = await adminApi.setModelPrice(pid, m.id, { price_in, price_out });
|
|
55
|
+
setBusy("");
|
|
56
|
+
if (!r.ok) {
|
|
57
|
+
setError(r.error ?? "save failed");
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
setEdits((e) => {
|
|
61
|
+
const n = { ...e };
|
|
62
|
+
delete n[k];
|
|
63
|
+
return n;
|
|
64
|
+
});
|
|
65
|
+
await load();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async function reset(pid: string, m: PricingModel) {
|
|
69
|
+
setBusy(keyOf(pid, m.id));
|
|
70
|
+
await adminApi.setModelPrice(pid, m.id, { price_in: null, price_out: null });
|
|
71
|
+
setBusy("");
|
|
72
|
+
setEdits((e) => {
|
|
73
|
+
const n = { ...e };
|
|
74
|
+
delete n[keyOf(pid, m.id)];
|
|
75
|
+
return n;
|
|
76
|
+
});
|
|
77
|
+
await load();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const providers = data?.providers.filter((p) => p.models.length > 0) ?? [];
|
|
81
|
+
|
|
82
|
+
const overrideCount = providers.reduce(
|
|
83
|
+
(n, p) => n + p.models.filter((m) => m.price_in != null || m.price_out != null).length,
|
|
84
|
+
0,
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
<details className="group overflow-hidden rounded-brand-lg border border-border bg-surface shadow-soft">
|
|
89
|
+
<summary className="flex cursor-pointer list-none items-center justify-between gap-3 px-4 py-3 [&::-webkit-details-marker]:hidden">
|
|
90
|
+
<CardTitle title="Pricing" sub="$/1M tokens — override the auto rate per model" />
|
|
91
|
+
<span className="flex items-center gap-2">
|
|
92
|
+
{overrideCount > 0 && <span className="text-[11px] text-text-subtle">{overrideCount} override{overrideCount > 1 ? "s" : ""}</span>}
|
|
93
|
+
<Icon name="expand_more" size={18} className="text-text-subtle transition-transform group-open:rotate-180" />
|
|
94
|
+
</span>
|
|
95
|
+
</summary>
|
|
96
|
+
<div className="border-t border-border-subtle p-4">
|
|
97
|
+
{error && <p className="mb-2 text-[12px] text-danger">{error}</p>}
|
|
98
|
+
{providers.length === 0 ? (
|
|
99
|
+
<Empty>No models yet. Add models to a provider to price them.</Empty>
|
|
100
|
+
) : (
|
|
101
|
+
<div className="space-y-2">
|
|
102
|
+
{providers.map((p) => {
|
|
103
|
+
const pOverrides = p.models.filter((m) => m.price_in != null || m.price_out != null).length;
|
|
104
|
+
return (
|
|
105
|
+
<details key={p.id} className="group/p overflow-hidden rounded-brand border border-border-subtle">
|
|
106
|
+
<summary className="flex cursor-pointer list-none items-center justify-between gap-2 bg-bg-alt px-3 py-2 [&::-webkit-details-marker]:hidden">
|
|
107
|
+
<span className="text-[11px] font-semibold uppercase tracking-wider text-text-subtle">{p.id}</span>
|
|
108
|
+
<span className="flex items-center gap-2 text-[11px] text-text-subtle">
|
|
109
|
+
<span>{p.models.length} model{p.models.length > 1 ? "s" : ""}{pOverrides > 0 ? ` · ${pOverrides} override` : ""}</span>
|
|
110
|
+
<Icon name="expand_more" size={16} className="transition-transform group-open/p:rotate-180" />
|
|
111
|
+
</span>
|
|
112
|
+
</summary>
|
|
113
|
+
<div className="">
|
|
114
|
+
{p.models.map((m) => {
|
|
115
|
+
const k = keyOf(p.id, m.id);
|
|
116
|
+
const overridden = m.price_in != null || m.price_out != null;
|
|
117
|
+
return (
|
|
118
|
+
<div key={m.id} className="flex items-center gap-2 border-b border-border-subtle px-3 py-2 last:border-b-0">
|
|
119
|
+
<span className="tnum min-w-0 flex-1 truncate text-[12.5px] text-text">{m.id}</span>
|
|
120
|
+
<label className="flex items-center gap-1 text-[11px] text-text-subtle">
|
|
121
|
+
in
|
|
122
|
+
<input
|
|
123
|
+
value={field(p.id, m, "in")}
|
|
124
|
+
onChange={(e) => setField(p.id, m.id, "in", e.target.value)}
|
|
125
|
+
placeholder={m.default_in == null ? "—" : String(m.default_in)}
|
|
126
|
+
inputMode="decimal"
|
|
127
|
+
className="w-16 rounded border border-border bg-bg px-1.5 py-1 text-right tnum text-[12px] text-text placeholder:text-text-subtle/60 focus:border-accent focus:outline-none"
|
|
128
|
+
/>
|
|
129
|
+
</label>
|
|
130
|
+
<label className="flex items-center gap-1 text-[11px] text-text-subtle">
|
|
131
|
+
out
|
|
132
|
+
<input
|
|
133
|
+
value={field(p.id, m, "out")}
|
|
134
|
+
onChange={(e) => setField(p.id, m.id, "out", e.target.value)}
|
|
135
|
+
placeholder={m.default_out == null ? "—" : String(m.default_out)}
|
|
136
|
+
inputMode="decimal"
|
|
137
|
+
className="w-16 rounded border border-border bg-bg px-1.5 py-1 text-right tnum text-[12px] text-text placeholder:text-text-subtle/60 focus:border-accent focus:outline-none"
|
|
138
|
+
/>
|
|
139
|
+
</label>
|
|
140
|
+
<button
|
|
141
|
+
onClick={() => save(p.id, m)}
|
|
142
|
+
disabled={busy === k}
|
|
143
|
+
className="rounded p-1 text-text-subtle hover:text-accent disabled:opacity-50"
|
|
144
|
+
title="Save override"
|
|
145
|
+
aria-label="Save price"
|
|
146
|
+
>
|
|
147
|
+
save
|
|
148
|
+
</button>
|
|
149
|
+
{overridden && (
|
|
150
|
+
<button
|
|
151
|
+
onClick={() => reset(p.id, m)}
|
|
152
|
+
disabled={busy === k}
|
|
153
|
+
className="rounded p-1 text-[11px] text-text-subtle hover:text-text disabled:opacity-50"
|
|
154
|
+
title="Clear override (use the auto rate)"
|
|
155
|
+
>
|
|
156
|
+
default
|
|
157
|
+
</button>
|
|
158
|
+
)}
|
|
159
|
+
</div>
|
|
160
|
+
);
|
|
161
|
+
})}
|
|
162
|
+
</div>
|
|
163
|
+
</details>
|
|
164
|
+
);
|
|
165
|
+
})}
|
|
166
|
+
</div>
|
|
167
|
+
)}
|
|
168
|
+
</div>
|
|
169
|
+
</details>
|
|
170
|
+
);
|
|
171
|
+
}
|