Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions .github/workflows/claude-code-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,16 @@ jobs:

# Check if this is a comment event with @claude mention
if [[ "${{ github.event_name }}" == "issue_comment" ]]; then
COMMENT_BODY="${{ github.event.comment.body }}"
if [[ "$COMMENT_BODY" == *"@claude"* ]] || [[ "$COMMENT_BODY" == *"@Claude"* ]]; then
# Use environment variable to safely handle multiline content with quotes
if echo "$COMMENT_BODY" | grep -i "@claude" > /dev/null; then
CLAUDE_REQUESTED=true
echo "Claude was mentioned in comment"
fi
fi

# Check if PR title or description contains request for Claude
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
PR_TITLE="${{ github.event.pull_request.title }}"
PR_BODY="${{ github.event.pull_request.body }}"
if [[ "$PR_TITLE" == *"@claude"* ]] || [[ "$PR_TITLE" == *"@Claude"* ]] || [[ "$PR_BODY" == *"@claude"* ]] || [[ "$PR_BODY" == *"@Claude"* ]]; then
if echo "$PR_TITLE" | grep -i "@claude" > /dev/null || echo "$PR_BODY" | grep -i "@claude" > /dev/null; then
CLAUDE_REQUESTED=true
echo "Claude was mentioned in PR title or description"
fi
Expand All @@ -54,6 +52,10 @@ jobs:
echo "claude_requested=false" >> $GITHUB_OUTPUT
echo "Claude review not requested - skipping"
fi
env:
COMMENT_BODY: ${{ github.event.comment.body }}
PR_TITLE: ${{ github.event.pull_request.title }}
PR_BODY: ${{ github.event.pull_request.body }}

- name: Check if most recent commit is from Claude
id: check-author
Expand Down
2 changes: 1 addition & 1 deletion apps/api/src/routes/activity.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ describe("activity endpoint", () => {

// Check model breakdown
const modelData = firstDay.modelBreakdown[0];
expect(modelData).toHaveProperty("model");
expect(modelData).toHaveProperty("id");
expect(modelData).toHaveProperty("provider");
expect(modelData).toHaveProperty("requestCount");
expect(modelData).toHaveProperty("inputTokens");
Expand Down
4 changes: 2 additions & 2 deletions apps/api/src/routes/activity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const activity = new OpenAPIHono<ServerTypes>();

// Define the response schema for model-specific usage
const modelUsageSchema = z.object({
model: z.string(),
id: z.string(),
provider: z.string(),
requestCount: z.number(),
inputTokens: z.number(),
Expand Down Expand Up @@ -208,7 +208,7 @@ activity.openapi(getActivity, async (c) => {

if (!dayModelMap.has(modelKey)) {
dayModelMap.set(modelKey, {
model,
id: model,
provider,
requestCount: 0,
inputTokens: 0,
Expand Down
16 changes: 8 additions & 8 deletions apps/gateway/src/api.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ if (hasOnlyModels) {

const filteredModels = models
// Filter out auto/custom models
.filter((model) => !["custom", "auto"].includes(model.model))
.filter((model) => !["custom", "auto"].includes(model.id))
// Filter out deactivated models
.filter((model) => !model.deactivatedAt || new Date() <= model.deactivatedAt);

Expand All @@ -64,7 +64,7 @@ const testModels = filteredModels
if (fullMode) {
// test root model without a specific provider
testCases.push({
model: model.model,
model: model.id,
providers: model.providers.filter(
(provider: ProviderModelMapping) => provider.test !== "skip",
),
Expand All @@ -84,9 +84,9 @@ const testModels = filteredModels
}

testCases.push({
model: `${provider.providerId}/${model.model}`,
model: `${provider.providerId}/${model.id}`,
providers: [provider],
originalModel: model.model, // Keep track of the original model for reference
originalModel: model.id, // Keep track of the original model for reference
});
}

Expand Down Expand Up @@ -118,9 +118,9 @@ const providerModels = filteredModels
}

testCases.push({
model: `${provider.providerId}/${model.model}`,
model: `${provider.providerId}/${model.id}`,
provider,
originalModel: model.model, // Keep track of the original model for reference
originalModel: model.id, // Keep track of the original model for reference
});
}

Expand Down Expand Up @@ -465,7 +465,7 @@ describe("e2e", () => {

test.each(
testModels.filter((m) => {
const modelDef = models.find((def) => def.model === m.model);
const modelDef = models.find((def) => def.id === m.model);
return (modelDef as any)?.jsonOutput === true;
}),
)("JSON output $model", getTestOptions(), async ({ model }) => {
Expand Down Expand Up @@ -791,7 +791,7 @@ describe("e2e", () => {
Authorization: `Bearer real-token`,
},
body: JSON.stringify({
model: multiProviderModel.model,
model: multiProviderModel.id,
messages: [
{
role: "user",
Expand Down
16 changes: 8 additions & 8 deletions apps/gateway/src/chat/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -944,7 +944,7 @@ chat.openapi(completions, async (c) => {
requestedModel = modelName as Model;
} else {
// First try to find by base model name
let modelDef = models.find((m) => m.model === modelName);
let modelDef = models.find((m) => m.id === modelName);

if (!modelDef) {
modelDef = models.find((m) =>
Expand Down Expand Up @@ -977,7 +977,7 @@ chat.openapi(completions, async (c) => {
requestedModel = modelName as Model;
}
}
} else if (models.find((m) => m.model === modelInput)) {
} else if (models.find((m) => m.id === modelInput)) {
requestedModel = modelInput as Model;
} else if (
models.find((m) => m.providers.find((p) => p.modelName === modelInput))
Expand All @@ -988,7 +988,7 @@ chat.openapi(completions, async (c) => {
const provider = model?.providers.find((p) => p.modelName === modelInput);

throw new HTTPException(400, {
message: `Model ${modelInput} must be requested with a provider prefix. Use the format: ${provider?.providerId}/${model?.model}`,
message: `Model ${modelInput} must be requested with a provider prefix. Use the format: ${provider?.providerId}/${model?.id}`,
});
} else {
throw new HTTPException(400, {
Expand Down Expand Up @@ -1028,7 +1028,7 @@ chat.openapi(completions, async (c) => {
};
} else {
modelInfo =
models.find((m) => m.model === requestedModel) ||
models.find((m) => m.id === requestedModel) ||
models.find((m) =>
m.providers.find((p) => p.modelName === requestedModel),
);
Expand Down Expand Up @@ -1190,7 +1190,7 @@ chat.openapi(completions, async (c) => {
}

for (const modelDef of models) {
if (modelDef.model === "auto" || modelDef.model === "custom") {
if (modelDef.id === "auto" || modelDef.id === "custom") {
continue;
}

Expand Down Expand Up @@ -1263,7 +1263,7 @@ chat.openapi(completions, async (c) => {
});
}

const modelWithPricing = models.find((m) => m.model === usedModel);
const modelWithPricing = models.find((m) => m.id === usedModel);

if (modelWithPricing) {
const cheapestResult = getCheapestFromAvailableProviders(
Expand Down Expand Up @@ -1313,12 +1313,12 @@ chat.openapi(completions, async (c) => {
} else {
finalModelInfo = models.find(
(m) =>
m.model === usedModel ||
m.id === usedModel ||
m.providers.some((p) => p.modelName === usedModel),
);
}

const baseModelName = finalModelInfo?.model || usedModel;
const baseModelName = finalModelInfo?.id || usedModel;

let url: string | undefined;

Expand Down
2 changes: 1 addition & 1 deletion apps/gateway/src/lib/costs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export function calculateCosts(
},
) {
// Find the model info - try both base model name and provider model name
let modelInfo = models.find((m) => m.model === model) as ModelDefinition;
let modelInfo = models.find((m) => m.id === model) as ModelDefinition;

if (!modelInfo) {
modelInfo = models.find((m) =>
Expand Down
8 changes: 4 additions & 4 deletions apps/gateway/src/models/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,10 @@ modelsApi.openapi(listModels, async (c) => {
firstProviderWithPricing?.imageInputPrice?.toString() || "0";

return {
id: model.model,
name: model.model,
id: model.id,
name: model.name || model.id,
created: Math.floor(Date.now() / 1000), // Current timestamp in seconds
description: `${model.model} provided by ${model.providers.map((p) => p.providerId).join(", ")}`,
description: `${model.id} provided by ${model.providers.map((p) => p.providerId).join(", ")}`,
architecture: {
input_modalities: inputModalities,
output_modalities: ["text"] as ["text"],
Expand Down Expand Up @@ -159,7 +159,7 @@ modelsApi.openapi(listModels, async (c) => {
Math.max(...model.providers.map((p) => p.contextSize || 0)) ||
undefined,
// TODO: supported_parameters should come from model definitions when available
supported_parameters: getSupportedParameters(model.model),
supported_parameters: getSupportedParameters(model.id),
// Add model-level capabilities
json_output: model.jsonOutput || false,
deprecated_at: model.deprecatedAt?.toISOString(),
Expand Down
4 changes: 2 additions & 2 deletions apps/next/src/app/providers/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ export default async function ProviderPage({ params }: ProviderPageProps) {
<h2 className="text-3xl font-bold mb-8">Available Models</h2>
<div className="grid gap-6 md:grid-cols-3">
{providerModels.map((model) => (
<Card key={model.model}>
<Card key={model.id}>
<CardHeader className="pb-2">
<div className="flex items-start justify-between gap-2">
<div className="flex-1 min-w-0">
<CardTitle className="text-base leading-tight line-clamp-1">
{model.model}
{model.id}
</CardTitle>
<CardDescription className="text-xs">
{model.providers[0].modelName}
Expand Down
4 changes: 2 additions & 2 deletions apps/next/src/components/activity/recent-logs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -266,8 +266,8 @@ export function RecentLogs({ initialData }: RecentLogsProps) {
<SelectContent>
<SelectItem value="all">All models</SelectItem>
{models.map((m) => (
<SelectItem key={m.model} value={m.model}>
{m.model}
<SelectItem key={m.id} value={m.id}>
{m.id}
</SelectItem>
))}
</SelectContent>
Expand Down
14 changes: 7 additions & 7 deletions apps/next/src/components/dashboard/activity-chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import type { TooltipProps } from "recharts";

// Helper function to get all unique models from the data
function getUniqueModels(
data: { modelBreakdown: { model: string }[] }[],
data: { modelBreakdown: { id: string }[] }[],
): string[] {
if (!data || data.length === 0) {
return [];
Expand All @@ -46,7 +46,7 @@ function getUniqueModels(
data.forEach((day) => {
if (day.modelBreakdown && day.modelBreakdown.length > 0) {
day.modelBreakdown.forEach((model) => {
allModels.add(model.model);
allModels.add(model.id);
});
}
});
Expand Down Expand Up @@ -84,7 +84,7 @@ interface TooltipPayload {
totalTokens: number;
cost: number;
modelBreakdown: {
model: string;
id: string;
requestCount: number;
cost: number;
totalTokens: number;
Expand Down Expand Up @@ -309,7 +309,7 @@ export function ActivityChart({ initialData }: ActivityChartProps) {
| string
| number
| {
model: string;
id: string;
requestCount: number;
cost: number;
totalTokens: number;
Expand All @@ -323,14 +323,14 @@ export function ActivityChart({ initialData }: ActivityChartProps) {
dayData.modelBreakdown.forEach((model) => {
switch (breakdownField) {
case "cost":
result[model.model] = model.cost;
result[model.id] = model.cost;
break;
case "tokens":
result[model.model] = model.totalTokens;
result[model.id] = model.totalTokens;
break;
case "requests":
default:
result[model.model] = model.requestCount;
result[model.id] = model.requestCount;
break;
}
});
Expand Down
14 changes: 7 additions & 7 deletions apps/next/src/components/models-supported.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import { useAppConfig } from "@/lib/config";
import { cn, formatContextSize } from "@/lib/utils";

interface ProviderModel {
model: string;
id: string;
providerId: ProviderId;
providerName: string;
inputPrice?: number;
Expand Down Expand Up @@ -84,7 +84,7 @@ const groupedProviders = modelDefinitions.reduce<
acc[provider.name] = [];
}
acc[provider.name].push({
model: def.model,
id: def.id,
providerId: map.providerId,
providerName: provider.name,
inputPrice: map.inputPrice,
Expand All @@ -100,7 +100,7 @@ const sortedProviderEntries = Object.entries(groupedProviders)
.sort(([a], [b]) => a.localeCompare(b))
.map(([providerName, models]) => [
providerName,
[...models].sort((a, b) => a.model.localeCompare(b.model)),
[...models].sort((a, b) => a.id.localeCompare(b.id)),
]) as [string, ProviderModel[]][];

const totalModels = modelDefinitions.length;
Expand Down Expand Up @@ -316,14 +316,14 @@ export const ModelsSupported = ({ isDashboard }: { isDashboard?: boolean }) => {
<div className="grid gap-4 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-3">
{models.map((model) => (
<Card
key={`${model.providerId}-${model.model}`}
key={`${model.providerId}-${model.id}`}
className="flex flex-col h-full hover:shadow-md transition-shadow"
>
<CardHeader className="pb-2">
<div className="flex items-start justify-between gap-2">
<div className="flex-1 min-w-0">
<CardTitle className="text-base leading-tight line-clamp-1">
{model.model}
{model.id}
</CardTitle>
<CardDescription className="text-xs">
{model.providerName}
Expand All @@ -333,10 +333,10 @@ export const ModelsSupported = ({ isDashboard }: { isDashboard?: boolean }) => {
variant="ghost"
size="sm"
className="h-6 w-6 p-0 shrink-0"
onClick={() => copyModelName(model.model)}
onClick={() => copyModelName(model.id)}
title="Copy model name"
>
{copiedModel === model.model ? (
{copiedModel === model.id ? (
<Check className="h-3 w-3 text-green-600" />
) : (
<Copy className="h-3 w-3" />
Expand Down
4 changes: 2 additions & 2 deletions apps/next/src/components/models/models-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ export function ModelsList() {
return (
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
{(models as readonly ModelDefinition[]).map((model) => (
<Card key={model.model} className="p-4">
<div className="text-lg font-semibold">{model.model}</div>
<Card key={model.id} className="p-4">
<div className="text-lg font-semibold">{model.name || model.id}</div>
<div className="text-sm text-muted-foreground mb-2">Providers:</div>
<div className="flex flex-wrap gap-2 mb-2">
{model.providers.map((provider) => (
Expand Down
Loading