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
17 changes: 17 additions & 0 deletions apps/docs/app/(home)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,23 @@ const docsOptions: DocsLayoutProps = {
),
},
],

sidebar: {
footer: (
<a
href="https://status.llmgateway.io/"
target="_blank"
rel="noopener noreferrer"
className="flex items-center justify-center gap-2 py-2 text-xs text-fd-muted-foreground hover:text-fd-foreground transition-colors"
>
<span className="relative flex h-2 w-2">
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-green-400 opacity-75" />
<span className="relative inline-flex h-2 w-2 rounded-full bg-green-500" />
</span>
All systems operational
</a>
),
},
};

export default function Layout({ children }: { children: ReactNode }) {
Expand Down
12 changes: 11 additions & 1 deletion apps/gateway/src/chat/tools/transform-streaming-to-openai.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1155,6 +1155,11 @@ export function transformStreamingToOpenai(
],
};
} else if (eventType === "metadata" && data.usage) {
const inputTokens = data.usage.inputTokens ?? 0;
const cacheReadTokens = data.usage.cacheReadInputTokens ?? 0;
const cacheWriteTokens = data.usage.cacheWriteInputTokens ?? 0;
const promptTokens = inputTokens + cacheReadTokens + cacheWriteTokens;

transformedData = {
id: `chatcmpl-${Date.now()}`,
object: "chat.completion.chunk",
Expand All @@ -1168,9 +1173,14 @@ export function transformStreamingToOpenai(
},
],
usage: {
prompt_tokens: data.usage.inputTokens ?? 0,
prompt_tokens: promptTokens,
completion_tokens: data.usage.outputTokens ?? 0,
total_tokens: data.usage.totalTokens ?? 0,
...(cacheReadTokens > 0 && {
prompt_tokens_details: {
cached_tokens: cacheReadTokens,
},
}),
},
};
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,18 @@ export const ChatSidebarSkeleton = ({
</SidebarContent>
<SidebarFooter className="border-t">
<CreditsDisplay organization={organization} isLoading={isOrgLoading} />
<a
href="https://status.llmgateway.io/"
target="_blank"
rel="noopener noreferrer"
className="flex items-center justify-center gap-2 px-4 pb-4 text-xs text-muted-foreground hover:text-foreground transition-colors"
>
<span className="relative flex h-2 w-2">
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-green-400 opacity-75" />
<span className="relative inline-flex h-2 w-2 rounded-full bg-green-500" />
</span>
All systems operational
</a>
</SidebarFooter>
</Sidebar>
);
Expand Down
12 changes: 12 additions & 0 deletions apps/playground/src/components/playground/chat-sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,18 @@ export function ChatSidebar({
<LogOutIcon className="h-4 w-4" />
</Button>
</div>
<a
href="https://status.llmgateway.io/"
target="_blank"
rel="noopener noreferrer"
className="flex items-center justify-center gap-2 px-4 pb-4 text-xs text-muted-foreground hover:text-foreground transition-colors"
>
<span className="relative flex h-2 w-2">
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-green-400 opacity-75" />
<span className="relative inline-flex h-2 w-2 rounded-full bg-green-500" />
</span>
All systems operational
</a>
</SidebarFooter>
</Sidebar>
);
Expand Down
12 changes: 12 additions & 0 deletions apps/playground/src/components/playground/image-sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,18 @@ export function ImageSidebar({
<LogOutIcon className="h-4 w-4" />
</Button>
</div>
<a
href="https://status.llmgateway.io/"
target="_blank"
rel="noopener noreferrer"
className="flex items-center justify-center gap-2 px-4 pb-4 text-xs text-muted-foreground hover:text-foreground transition-colors"
>
<span className="relative flex h-2 w-2">
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-green-400 opacity-75" />
<span className="relative inline-flex h-2 w-2 rounded-full bg-green-500" />
</span>
All systems operational
</a>
</SidebarFooter>
</Sidebar>
);
Expand Down
12 changes: 12 additions & 0 deletions apps/ui/src/components/landing/footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,18 @@ export default function Footer() {
&copy; {new Date().getFullYear()} LLM Gateway. All rights reserved.
</p>
<div className="flex items-center gap-6">
<a
href="https://status.llmgateway.io/"
target="_blank"
rel="noopener noreferrer"
className="flex items-center gap-2 text-sm text-muted-foreground hover:text-foreground transition-colors"
>
<span className="relative flex h-2.5 w-2.5">
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-green-400 opacity-75" />
<span className="relative inline-flex h-2.5 w-2.5 rounded-full bg-green-500" />
</span>
All systems operational
</a>
<Link
href="/legal/privacy"
className="text-sm text-muted-foreground hover:underline underline-offset-4 hover:text-foreground"
Expand Down
17 changes: 2 additions & 15 deletions ee/audit/src/audit-logger.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import {
auditLog,
db,
eq,
organization as organizationTable,
type AuditLogAction,
type AuditLogMetadata,
type AuditLogResourceType,
Expand All @@ -20,24 +18,13 @@ export interface LogAuditEventParams {

/**
* Logs an audit event for an organization.
* Only logs if the organization has an enterprise plan.
* Always logs regardless of plan — the enterprise check is enforced
* at the API read layer so orgs upgrading later already have history.
*/
export async function logAuditEvent(
params: LogAuditEventParams,
): Promise<void> {
try {
// Check if organization has enterprise plan before logging
const org = await db
.select({ plan: organizationTable.plan })
.from(organizationTable)
.where(eq(organizationTable.id, params.organizationId))
.limit(1);

// Only log for enterprise organizations
if (!org[0] || org[0].plan !== "enterprise") {
return;
}

await db.insert(auditLog).values({
organizationId: params.organizationId,
userId: params.userId,
Expand Down
5 changes: 5 additions & 0 deletions packages/db/migrations/1773841690_keen_toad_men.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
DROP INDEX IF EXISTS "model_history_model_id_minute_timestamp_idx";--> statement-breakpoint
DROP INDEX IF EXISTS "model_provider_mapping_history_model_id_minute_timestamp_idx";--> statement-breakpoint
DROP INDEX IF EXISTS "model_provider_mapping_history_id_ts_idx";--> statement-breakpoint
DROP INDEX IF EXISTS "project_hourly_model_stats_used_model_hour_timestamp_idx";--> statement-breakpoint
DROP INDEX IF EXISTS "project_hourly_model_stats_p_m_time_idx";
5 changes: 5 additions & 0 deletions packages/db/migrations/1773841805_dashing_sentinels.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
CREATE INDEX IF NOT EXISTS "model_history_model_id_minute_timestamp_idx" ON "model_history" ("model_id","minute_timestamp");--> statement-breakpoint
CREATE INDEX IF NOT EXISTS "model_provider_mapping_history_model_id_minute_timestamp_idx" ON "model_provider_mapping_history" ("model_id","minute_timestamp");--> statement-breakpoint
CREATE INDEX IF NOT EXISTS "model_provider_mapping_history_id_ts_idx" ON "model_provider_mapping_history" ("provider_id","model_id","minute_timestamp");--> statement-breakpoint
CREATE INDEX IF NOT EXISTS "project_hourly_model_stats_used_model_hour_timestamp_idx" ON "project_hourly_model_stats" ("used_model","hour_timestamp");--> statement-breakpoint
CREATE INDEX IF NOT EXISTS "project_hourly_model_stats_p_m_time_idx" ON "project_hourly_model_stats" ("used_provider","used_model","hour_timestamp");
Loading