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
11 changes: 2 additions & 9 deletions src/app/api/openrouter/[...path]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ import { handleRequestLogging } from '@/lib/handleRequestLogging';
import { grokCodeFastOptimizedRequest } from '@/lib/custom-llm/customLlmRequest';
import { normalizeModelId } from '@/lib/model-utils';
import { isForbiddenFreeModel } from '@/lib/forbidden-free-models';
import { isActiveReviewPromo } from '@/lib/code-reviews/core/constants';
import { isCloudflareIP } from '@/lib/cloudflare-ip';
import { applyResolvedAutoModel, isKiloAutoModel } from '@/lib/kilo-auto-model';
import { fixOpenCodeDuplicateReasoning } from '@/lib/providers/fixOpenCodeDuplicateReasoning';
Expand Down Expand Up @@ -416,12 +415,7 @@ export async function POST(request: NextRequest): Promise<NextResponseType<unkno
if (!isAnonymousContext(user) && !bypassAccessCheck) {
const { balance, settings, plan } = await balanceAndSettingsPromise;

if (
balance <= 0 &&
!isFreeModel(originalModelIdLowerCased) &&
!userByok &&
!isActiveReviewPromo(botId, originalModelIdLowerCased)
) {
if (balance <= 0 && !isFreeModel(originalModelIdLowerCased) && !userByok) {
return await usageLimitExceededResponse(user, balance);
}

Expand Down Expand Up @@ -605,8 +599,7 @@ export async function POST(request: NextRequest): Promise<NextResponseType<unkno

const isFreeModelRequiringCostRemoval =
(provider.id === 'openrouter' || provider.id === 'vercel') &&
(isKiloFreeModel(originalModelIdLowerCased) ||
isActiveReviewPromo(botId, originalModelIdLowerCased));
isKiloFreeModel(originalModelIdLowerCased);
const isStealthModelRequiringNameRemoval = isKiloStealthModel(originalModelIdLowerCased);
const isProviderRequiringResponseFixes = provider.id === 'corethink';

Expand Down
11 changes: 1 addition & 10 deletions src/components/code-reviews/ReviewConfigForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import { ModelCombobox } from '@/components/shared/ModelCombobox';
import { cn } from '@/lib/utils';
import { RepositoryMultiSelect, type Repository } from './RepositoryMultiSelect';
import { PRIMARY_DEFAULT_MODEL } from '@/lib/models';
import { REVIEW_PROMO_MODEL, REVIEW_PROMO_END } from '@/lib/code-reviews/core/constants';
import {
getAvailableThinkingEfforts,
thinkingEffortLabel,
Expand Down Expand Up @@ -195,14 +194,6 @@ export function ReviewConfigForm({
// Fetch available models
const { modelOptions, isLoadingModels } = useOrganizationModels(organizationId);

const promoModelOptions = useMemo(() => {
const promoActive = Date.now() < Date.parse(REVIEW_PROMO_END);
if (!promoActive) return modelOptions;
return modelOptions.map(m =>
m.id === REVIEW_PROMO_MODEL ? { ...m, name: `${m.name} (free)` } : m
);
}, [modelOptions]);

// Local state
const [isEnabled, setIsEnabled] = useState(false);
const [reviewStyle, setReviewStyle] = useState<'strict' | 'balanced' | 'lenient' | 'roast'>(
Expand Down Expand Up @@ -553,7 +544,7 @@ export function ReviewConfigForm({
{/* AI Model Selection */}
<ModelCombobox
label="AI Model"
models={promoModelOptions}
models={modelOptions}
value={selectedModel}
onValueChange={setSelectedModel}
isLoading={isLoadingModels}
Expand Down
16 changes: 0 additions & 16 deletions src/lib/code-reviews/core/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,6 @@ export const DEFAULT_CODE_REVIEW_MODEL = 'anthropic/claude-sonnet-4.6';
*/
export const DEFAULT_CODE_REVIEW_MODE = 'code' as const;

// ============================================================================
// Sonnet 4.6 Review Promotion
// ============================================================================

export const REVIEW_PROMO_MODEL = 'anthropic/claude-sonnet-4.6';
export const REVIEW_PROMO_START = '2026-02-18T14:00:00Z'; // used only for admin logging
export const REVIEW_PROMO_END = '2026-02-25T14:00:00Z';

/** Single source of truth: is the free-review promo active for this request? */
export function isActiveReviewPromo(botId: string | undefined, model: string): boolean {
if (botId !== 'reviewer') return false;
if (model !== REVIEW_PROMO_MODEL) return false;

return Date.now() < Date.parse(REVIEW_PROMO_END);
}

// ============================================================================
// Feature Flags
// ============================================================================
Expand Down
13 changes: 0 additions & 13 deletions src/lib/code-reviews/triggers/prepare-review-payload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,6 @@ import {
DEFAULT_CODE_REVIEW_MODEL,
DEFAULT_CODE_REVIEW_MODE,
FEATURE_FLAG_INCREMENTAL_REVIEW,
isActiveReviewPromo,
REVIEW_PROMO_START,
REVIEW_PROMO_END,
} from '../core/constants';
import type { Owner } from '../core';
import { generateReviewPrompt } from '../prompts/generate-prompt';
Expand Down Expand Up @@ -440,16 +437,6 @@ export async function prepareReviewPayload(
...(gateThreshold !== 'off' ? { gateThreshold } : {}),
};

if (isActiveReviewPromo('reviewer', sessionInput.model)) {
logExceptInTest('[prepareReviewPayload] Promotional model selected for code review', {
reviewId,
owner,
model: sessionInput.model,
promoStart: REVIEW_PROMO_START,
promoEnd: REVIEW_PROMO_END,
});
}

// Log the session input for GitLab
if (platform === PLATFORM.GITLAB) {
logExceptInTest('[prepareReviewPayload] GitLab session input prepared', {
Expand Down
9 changes: 2 additions & 7 deletions src/lib/processUsage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import { getEffectiveKiloPassThreshold } from '@/lib/kilo-pass/threshold';
import { appendKiloPassAuditLog } from '@/lib/kilo-pass/issuance';
import { KiloPassAuditLogAction, KiloPassAuditLogResult } from '@/lib/kilo-pass/enums';
import { reportAbuseCost } from '@/lib/abuse-service';
import { isActiveReviewPromo } from '@/lib/code-reviews/core/constants';
import type {
BalanceUpdateResult,
ChatCompletionChunk,
Expand Down Expand Up @@ -839,14 +838,10 @@ async function processTokenData(
console.error('[Abuse] Failed to report cost:', error);
});

// Preserve the real cost before zeroing for free/BYOK/promo
// Preserve the real cost before zeroing for free/BYOK
usageStats.market_cost = usageStats.cost_mUsd;

if (
isFreeModel(usageContext.requested_model) ||
usageContext.user_byok ||
isActiveReviewPromo(usageContext.botId, usageContext.requested_model)
) {
if (isFreeModel(usageContext.requested_model) || usageContext.user_byok) {
usageStats.cost_mUsd = 0;
usageStats.cacheDiscount_mUsd = 0;
}
Expand Down
77 changes: 1 addition & 76 deletions src/routers/admin-code-reviews-router.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,8 @@
import { adminProcedure, createTRPCRouter } from '@/lib/trpc/init';
import { db } from '@/lib/drizzle';
import {
cloud_agent_code_reviews,
kilocode_users,
microdollar_usage,
microdollar_usage_metadata,
organizations,
} from '@kilocode/db/schema';
import { cloud_agent_code_reviews, kilocode_users, organizations } from '@kilocode/db/schema';
import * as z from 'zod';
import { sql, and, gte, lt, eq, isNotNull, isNull, desc, ilike, or, type SQL } from 'drizzle-orm';
import {
REVIEW_PROMO_MODEL,
REVIEW_PROMO_START,
REVIEW_PROMO_END,
isActiveReviewPromo,
} from '@/lib/code-reviews/core/constants';

/**
* SQL condition that identifies billing/credits errors (402 Payment Required).
Expand Down Expand Up @@ -639,67 +627,4 @@ export const adminCodeReviewsRouter = createTRPCRouter({

return result;
}),

getReviewPromotionStats: adminProcedure.query(async () => {
// Aggregates: total requests, unique users, unique orgs
const aggregates = await db
.select({
total_requests: sql<number>`COUNT(*)`,
unique_users: sql<number>`COUNT(DISTINCT ${microdollar_usage.kilo_user_id})`,
unique_orgs: sql<number>`COUNT(DISTINCT ${microdollar_usage.organization_id})`,
})
.from(microdollar_usage)
.innerJoin(
microdollar_usage_metadata,
eq(microdollar_usage.id, microdollar_usage_metadata.id)
)
.where(
and(
eq(microdollar_usage.requested_model, REVIEW_PROMO_MODEL),
eq(microdollar_usage.cost, 0),
sql`(${microdollar_usage_metadata.is_user_byok} IS NULL OR ${microdollar_usage_metadata.is_user_byok} = false)`,
gte(microdollar_usage.created_at, REVIEW_PROMO_START),
lt(microdollar_usage.created_at, REVIEW_PROMO_END)
)
);

// Daily breakdown
const daily = await db
.select({
day: sql<string>`DATE_TRUNC('day', ${microdollar_usage.created_at})::date::text`,
total: sql<number>`COUNT(*)`,
unique_users: sql<number>`COUNT(DISTINCT ${microdollar_usage.kilo_user_id})`,
})
.from(microdollar_usage)
.innerJoin(
microdollar_usage_metadata,
eq(microdollar_usage.id, microdollar_usage_metadata.id)
)
.where(
and(
eq(microdollar_usage.requested_model, REVIEW_PROMO_MODEL),
eq(microdollar_usage.cost, 0),
sql`(${microdollar_usage_metadata.is_user_byok} IS NULL OR ${microdollar_usage_metadata.is_user_byok} = false)`,
gte(microdollar_usage.created_at, REVIEW_PROMO_START),
lt(microdollar_usage.created_at, REVIEW_PROMO_END)
)
)
.groupBy(sql`DATE_TRUNC('day', ${microdollar_usage.created_at})`)
.orderBy(sql`DATE_TRUNC('day', ${microdollar_usage.created_at})`);

const agg = aggregates[0];
return {
promoActive: isActiveReviewPromo('reviewer', REVIEW_PROMO_MODEL),
promoStart: REVIEW_PROMO_START,
promoEnd: REVIEW_PROMO_END,
totalRequests: Number(agg.total_requests) || 0,
uniqueUsers: Number(agg.unique_users) || 0,
uniqueOrgs: Number(agg.unique_orgs) || 0,
daily: daily.map(row => ({
day: row.day,
total: Number(row.total) || 0,
uniqueUsers: Number(row.unique_users) || 0,
})),
};
}),
});
Loading
Loading