agy تنها ارائه‌دهندهٔ مدل؛ حذف بخش ارائه‌دهنده‌ها و افزودن زنجیرهٔ انتخاب مدل

- حذف کامل providerهای mock و openai_compatible: دامنه، آداپوترها، رجیستری، کانفیگ، seed و رابطٔ مدیریت
- بخش «ارائه‌دهنده‌ها» از کنسول حذف شد؛ ورود اکانت‌ها فقط از صفحهٔ اکانت‌های agy
- صفحهٔ مدل‌ها بازطراحی شد: ارائه‌دهنده → اکانت → مدل (کاتالوگ لحظه‌ای و زندهٔ همان اکانت از Google) → افورت استدلال؛ بدون هیچ ورود دستی نام مدل
- مدل‌ها ستون reasoning_effort گرفتند؛ آداپتور آن را به thinkingConfig (بودجهٔ ۱۰۲۴ تا ۳۲۷۶۸) ترجمه می‌کند و فقط به مدل‌های استدلالی می‌فرستد
- مهاجرت c2d3e4f5b6a7: افزودن reasoning_effort و حذف ردیف‌های providerهای قدیمی
- تست‌ها: ۲۴۶ تست بک‌اند و ۵۱ تست فرانت سبز؛ ruff و mypy و tsc و eslint تمیز
This commit is contained in:
mjalmoudy94
2026-10-13 10:01:11 +03:30
parent a2284db4f4
commit da5a2a5d1a
29 changed files with 906 additions and 995 deletions
+48 -32
View File
@@ -10,14 +10,52 @@ export type Role = "owner" | "admin" | "manager" | "member" | "viewer";
export type MembershipStatus = "active" | "invited" | "suspended";
/** Provider kinds the AI Control Plane can talk to. */
export type ProviderType =
| "mock"
| "openai_compatible"
| "anthropic"
| "gemini"
| "openrouter"
| "agy";
/**
* Provider kinds the AI Control Plane can talk to. agy (Google Antigravity)
* is the only one — the platform no longer has a provider picker.
*/
export type ProviderType = "agy";
/** agy reasoning efforts, cheapest first. Mirrors the backend's list. */
export type ReasoningEffort = "minimal" | "low" | "medium" | "high" | "xhigh";
export const REASONING_EFFORTS: ReasoningEffort[] = [
"minimal",
"low",
"medium",
"high",
"xhigh",
];
const EFFORT_LABELS: Record<ReasoningEffort, string> = {
minimal: "حداقل",
low: "کم",
medium: "متوسط",
high: "زیاد",
xhigh: "بسیار زیاد",
};
/**
* Reasoning efforts a model may be configured with, or an empty list when the
* model cannot think — the backend rejects a thinking config everywhere else.
* Same marker rule as the agy adapter: thinking-capable ids contain one of
* `thinking` / `gemini-3` / `gemini-2.5-pro` / `gemini-2.5-flash`, image
* models are always excluded.
*/
export function effortsForModel(modelId: string): ReasoningEffort[] {
const lower = modelId.toLowerCase();
if (lower.includes("image")) return [];
const canThink =
lower.includes("thinking") ||
lower.includes("gemini-3") ||
lower.includes("gemini-2.5-pro") ||
lower.includes("gemini-2.5-flash");
return canThink ? [...REASONING_EFFORTS] : [];
}
export function effortLabel(effort: string): string {
return EFFORT_LABELS[effort as ReasoningEffort] ?? effort;
}
/** Rotation-pool lifecycle of one agy account. */
export type AgyAccountStatus = "active" | "cooldown" | "error";
@@ -182,15 +220,6 @@ export interface Repository {
private: boolean;
}
export interface AdminProvider {
id: string;
name: string;
type: string;
base_url: string;
is_active: boolean;
created_at: string;
}
export interface AdminModel {
id: string;
provider_id: string;
@@ -199,6 +228,8 @@ export interface AdminModel {
capabilities: string[];
input_price_per_1m: number;
output_price_per_1m: number;
/** agy reasoning effort ("" = provider default). Owner-only metadata. */
reasoning_effort: string;
is_active: boolean;
}
@@ -228,21 +259,6 @@ export interface AdminOrganization {
created_at: string;
}
/**
* A stored provider credential.
*
* There is no field here that can carry a plaintext key — the API only ever
* returns a masked form, and on list it returns a fixed mask because the
* plaintext is unrecoverable by design.
*/
export interface AdminCredential {
id: string;
provider_id: string;
name: string;
masked_key: string;
is_active: boolean;
}
/** Result of a routing dry-run: which model a mode would pick, and why. */
export interface ModelChoice {
mode: string;