diff --git a/docs/management-api.md b/docs/management-api.md index 0d20993..98fcb57 100644 --- a/docs/management-api.md +++ b/docs/management-api.md @@ -297,7 +297,11 @@ curl -sS "${METAPI_ADMIN_BASE_URL}/api/sites" \ `GET /api/accounts` -返回当前全部账号,以及关联站点、凭证模式、能力信息、今日花费、运行健康状态等聚合字段。 +返回账号快照对象,而不是裸数组。响应里包含: + +- `generatedAt`:快照生成时间 +- `accounts`:当前全部账号,以及关联站点、凭证模式、能力信息、今日花费、运行健康状态等聚合字段 +- `sites`:前端常用的站点列表快照 示例: @@ -309,26 +313,37 @@ curl -sS "${METAPI_ADMIN_BASE_URL}/api/accounts" \ 示例响应: ```json -[ - { - "id": 1, - "siteId": 1, - "username": "alice", - "status": "active", - "credentialMode": "apikey", - "capabilities": { - "canCheckin": false, - "canRefreshBalance": false, - "proxyOnly": true - }, - "site": { +{ + "generatedAt": "2026-04-09T06:00:00.000Z", + "accounts": [ + { + "id": 1, + "siteId": 1, + "username": "alice", + "status": "active", + "credentialMode": "apikey", + "capabilities": { + "canCheckin": false, + "canRefreshBalance": false, + "proxyOnly": true + }, + "site": { + "id": 1, + "name": "My New API", + "url": "https://api.example.com", + "platform": "new-api" + } + } + ], + "sites": [ + { "id": 1, "name": "My New API", "url": "https://api.example.com", "platform": "new-api" } - } -] + ] +} ``` ### 2. 验证凭证 diff --git a/drizzle/0022_admin_snapshots.sql b/drizzle/0022_admin_snapshots.sql new file mode 100644 index 0000000..4bda87a --- /dev/null +++ b/drizzle/0022_admin_snapshots.sql @@ -0,0 +1,15 @@ +CREATE TABLE `admin_snapshots` ( + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `namespace` text NOT NULL, + `snapshot_key` text NOT NULL, + `payload` text NOT NULL, + `generated_at` text NOT NULL, + `expires_at` text NOT NULL, + `stale_until` text NOT NULL, + `created_at` text DEFAULT (datetime('now')), + `updated_at` text DEFAULT (datetime('now')) +); +--> statement-breakpoint +CREATE UNIQUE INDEX `admin_snapshots_namespace_key_unique` ON `admin_snapshots` (`namespace`,`snapshot_key`);--> statement-breakpoint +CREATE INDEX `admin_snapshots_expires_at_idx` ON `admin_snapshots` (`expires_at`);--> statement-breakpoint +CREATE INDEX `admin_snapshots_stale_until_idx` ON `admin_snapshots` (`stale_until`); \ No newline at end of file diff --git a/drizzle/0023_usage_aggregates.sql b/drizzle/0023_usage_aggregates.sql new file mode 100644 index 0000000..665dbe1 --- /dev/null +++ b/drizzle/0023_usage_aggregates.sql @@ -0,0 +1,79 @@ +CREATE TABLE `analytics_projection_checkpoints` ( + `projector_key` text PRIMARY KEY NOT NULL, + `time_zone` text DEFAULT 'Local' NOT NULL, + `last_proxy_log_id` integer DEFAULT 0 NOT NULL, + `watermark_created_at` text, + `recompute_from_id` integer, + `recompute_requested_at` text, + `recompute_reason` text, + `recompute_started_at` text, + `recompute_completed_at` text, + `last_projected_at` text, + `last_successful_at` text, + `last_error` text, + `created_at` text DEFAULT (datetime('now')), + `updated_at` text DEFAULT (datetime('now')) +); +--> statement-breakpoint +CREATE INDEX `analytics_projection_checkpoints_recompute_from_id_idx` ON `analytics_projection_checkpoints` (`recompute_from_id`);--> statement-breakpoint +CREATE TABLE `model_day_usage` ( + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `local_day` text NOT NULL, + `site_id` integer NOT NULL, + `model` text NOT NULL, + `total_calls` integer DEFAULT 0 NOT NULL, + `success_calls` integer DEFAULT 0 NOT NULL, + `failed_calls` integer DEFAULT 0 NOT NULL, + `total_tokens` integer DEFAULT 0 NOT NULL, + `total_spend` real DEFAULT 0 NOT NULL, + `total_latency_ms` integer DEFAULT 0 NOT NULL, + `latency_count` integer DEFAULT 0 NOT NULL, + `created_at` text DEFAULT (datetime('now')), + `updated_at` text DEFAULT (datetime('now')), + FOREIGN KEY (`site_id`) REFERENCES `sites`(`id`) ON UPDATE no action ON DELETE cascade +); +--> statement-breakpoint +CREATE UNIQUE INDEX `model_day_usage_day_site_model_unique` ON `model_day_usage` (`local_day`,`site_id`,`model`);--> statement-breakpoint +CREATE INDEX `model_day_usage_day_idx` ON `model_day_usage` (`local_day`);--> statement-breakpoint +CREATE INDEX `model_day_usage_site_id_idx` ON `model_day_usage` (`site_id`);--> statement-breakpoint +CREATE INDEX `model_day_usage_model_idx` ON `model_day_usage` (`model`);--> statement-breakpoint +CREATE TABLE `site_day_usage` ( + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `local_day` text NOT NULL, + `site_id` integer NOT NULL, + `total_calls` integer DEFAULT 0 NOT NULL, + `success_calls` integer DEFAULT 0 NOT NULL, + `failed_calls` integer DEFAULT 0 NOT NULL, + `total_tokens` integer DEFAULT 0 NOT NULL, + `total_summary_spend` real DEFAULT 0 NOT NULL, + `total_site_spend` real DEFAULT 0 NOT NULL, + `total_latency_ms` integer DEFAULT 0 NOT NULL, + `latency_count` integer DEFAULT 0 NOT NULL, + `created_at` text DEFAULT (datetime('now')), + `updated_at` text DEFAULT (datetime('now')), + FOREIGN KEY (`site_id`) REFERENCES `sites`(`id`) ON UPDATE no action ON DELETE cascade +); +--> statement-breakpoint +CREATE UNIQUE INDEX `site_day_usage_day_site_unique` ON `site_day_usage` (`local_day`,`site_id`);--> statement-breakpoint +CREATE INDEX `site_day_usage_day_idx` ON `site_day_usage` (`local_day`);--> statement-breakpoint +CREATE INDEX `site_day_usage_site_id_idx` ON `site_day_usage` (`site_id`);--> statement-breakpoint +CREATE TABLE `site_hour_usage` ( + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `bucket_start_utc` text NOT NULL, + `site_id` integer NOT NULL, + `total_calls` integer DEFAULT 0 NOT NULL, + `success_calls` integer DEFAULT 0 NOT NULL, + `failed_calls` integer DEFAULT 0 NOT NULL, + `total_tokens` integer DEFAULT 0 NOT NULL, + `total_summary_spend` real DEFAULT 0 NOT NULL, + `total_site_spend` real DEFAULT 0 NOT NULL, + `total_latency_ms` integer DEFAULT 0 NOT NULL, + `latency_count` integer DEFAULT 0 NOT NULL, + `created_at` text DEFAULT (datetime('now')), + `updated_at` text DEFAULT (datetime('now')), + FOREIGN KEY (`site_id`) REFERENCES `sites`(`id`) ON UPDATE no action ON DELETE cascade +); +--> statement-breakpoint +CREATE UNIQUE INDEX `site_hour_usage_hour_site_unique` ON `site_hour_usage` (`bucket_start_utc`,`site_id`);--> statement-breakpoint +CREATE INDEX `site_hour_usage_hour_idx` ON `site_hour_usage` (`bucket_start_utc`);--> statement-breakpoint +CREATE INDEX `site_hour_usage_site_id_idx` ON `site_hour_usage` (`site_id`); \ No newline at end of file diff --git a/drizzle/0024_projection_leases.sql b/drizzle/0024_projection_leases.sql new file mode 100644 index 0000000..422ee56 --- /dev/null +++ b/drizzle/0024_projection_leases.sql @@ -0,0 +1,79 @@ +ALTER TABLE `analytics_projection_checkpoints` ADD `lease_owner` text;--> statement-breakpoint +ALTER TABLE `analytics_projection_checkpoints` ADD `lease_token` text;--> statement-breakpoint +ALTER TABLE `analytics_projection_checkpoints` ADD `lease_expires_at` text;--> statement-breakpoint +CREATE INDEX `analytics_projection_checkpoints_lease_expires_at_idx` ON `analytics_projection_checkpoints` (`lease_expires_at`);--> statement-breakpoint +PRAGMA foreign_keys=OFF;--> statement-breakpoint +CREATE TABLE `__new_model_day_usage` ( + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `local_day` text NOT NULL, + `site_id` integer NOT NULL, + `model` text NOT NULL, + `total_calls` integer DEFAULT 0 NOT NULL, + `success_calls` integer DEFAULT 0 NOT NULL, + `failed_calls` integer DEFAULT 0 NOT NULL, + `total_tokens` integer DEFAULT 0 NOT NULL, + `total_spend` real DEFAULT 0 NOT NULL, + `total_latency_ms` integer DEFAULT 0 NOT NULL, + `latency_count` integer DEFAULT 0 NOT NULL, + `created_at` text DEFAULT (datetime('now')), + `updated_at` text DEFAULT (datetime('now')), + FOREIGN KEY (`site_id`) REFERENCES `sites`(`id`) ON UPDATE no action ON DELETE cascade, + CONSTRAINT "model_day_usage_non_negative" CHECK("__new_model_day_usage"."total_calls" >= 0 and "__new_model_day_usage"."success_calls" >= 0 and "__new_model_day_usage"."failed_calls" >= 0 and "__new_model_day_usage"."total_tokens" >= 0 and "__new_model_day_usage"."total_spend" >= 0 and "__new_model_day_usage"."total_latency_ms" >= 0 and "__new_model_day_usage"."latency_count" >= 0) +); +--> statement-breakpoint +INSERT INTO `__new_model_day_usage`("id", "local_day", "site_id", "model", "total_calls", "success_calls", "failed_calls", "total_tokens", "total_spend", "total_latency_ms", "latency_count", "created_at", "updated_at") SELECT "id", "local_day", "site_id", "model", "total_calls", "success_calls", "failed_calls", "total_tokens", "total_spend", "total_latency_ms", "latency_count", "created_at", "updated_at" FROM `model_day_usage`;--> statement-breakpoint +DROP TABLE `model_day_usage`;--> statement-breakpoint +ALTER TABLE `__new_model_day_usage` RENAME TO `model_day_usage`;--> statement-breakpoint +PRAGMA foreign_keys=ON;--> statement-breakpoint +CREATE UNIQUE INDEX `model_day_usage_day_site_model_unique` ON `model_day_usage` (`local_day`,`site_id`,`model`);--> statement-breakpoint +CREATE INDEX `model_day_usage_day_idx` ON `model_day_usage` (`local_day`);--> statement-breakpoint +CREATE INDEX `model_day_usage_site_id_idx` ON `model_day_usage` (`site_id`);--> statement-breakpoint +CREATE INDEX `model_day_usage_model_idx` ON `model_day_usage` (`model`);--> statement-breakpoint +CREATE TABLE `__new_site_day_usage` ( + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `local_day` text NOT NULL, + `site_id` integer NOT NULL, + `total_calls` integer DEFAULT 0 NOT NULL, + `success_calls` integer DEFAULT 0 NOT NULL, + `failed_calls` integer DEFAULT 0 NOT NULL, + `total_tokens` integer DEFAULT 0 NOT NULL, + `total_summary_spend` real DEFAULT 0 NOT NULL, + `total_site_spend` real DEFAULT 0 NOT NULL, + `total_latency_ms` integer DEFAULT 0 NOT NULL, + `latency_count` integer DEFAULT 0 NOT NULL, + `created_at` text DEFAULT (datetime('now')), + `updated_at` text DEFAULT (datetime('now')), + FOREIGN KEY (`site_id`) REFERENCES `sites`(`id`) ON UPDATE no action ON DELETE cascade, + CONSTRAINT "site_day_usage_non_negative" CHECK("__new_site_day_usage"."total_calls" >= 0 and "__new_site_day_usage"."success_calls" >= 0 and "__new_site_day_usage"."failed_calls" >= 0 and "__new_site_day_usage"."total_tokens" >= 0 and "__new_site_day_usage"."total_summary_spend" >= 0 and "__new_site_day_usage"."total_site_spend" >= 0 and "__new_site_day_usage"."total_latency_ms" >= 0 and "__new_site_day_usage"."latency_count" >= 0) +); +--> statement-breakpoint +INSERT INTO `__new_site_day_usage`("id", "local_day", "site_id", "total_calls", "success_calls", "failed_calls", "total_tokens", "total_summary_spend", "total_site_spend", "total_latency_ms", "latency_count", "created_at", "updated_at") SELECT "id", "local_day", "site_id", "total_calls", "success_calls", "failed_calls", "total_tokens", "total_summary_spend", "total_site_spend", "total_latency_ms", "latency_count", "created_at", "updated_at" FROM `site_day_usage`;--> statement-breakpoint +DROP TABLE `site_day_usage`;--> statement-breakpoint +ALTER TABLE `__new_site_day_usage` RENAME TO `site_day_usage`;--> statement-breakpoint +CREATE UNIQUE INDEX `site_day_usage_day_site_unique` ON `site_day_usage` (`local_day`,`site_id`);--> statement-breakpoint +CREATE INDEX `site_day_usage_day_idx` ON `site_day_usage` (`local_day`);--> statement-breakpoint +CREATE INDEX `site_day_usage_site_id_idx` ON `site_day_usage` (`site_id`);--> statement-breakpoint +CREATE TABLE `__new_site_hour_usage` ( + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `bucket_start_utc` text NOT NULL, + `site_id` integer NOT NULL, + `total_calls` integer DEFAULT 0 NOT NULL, + `success_calls` integer DEFAULT 0 NOT NULL, + `failed_calls` integer DEFAULT 0 NOT NULL, + `total_tokens` integer DEFAULT 0 NOT NULL, + `total_summary_spend` real DEFAULT 0 NOT NULL, + `total_site_spend` real DEFAULT 0 NOT NULL, + `total_latency_ms` integer DEFAULT 0 NOT NULL, + `latency_count` integer DEFAULT 0 NOT NULL, + `created_at` text DEFAULT (datetime('now')), + `updated_at` text DEFAULT (datetime('now')), + FOREIGN KEY (`site_id`) REFERENCES `sites`(`id`) ON UPDATE no action ON DELETE cascade, + CONSTRAINT "site_hour_usage_non_negative" CHECK("__new_site_hour_usage"."total_calls" >= 0 and "__new_site_hour_usage"."success_calls" >= 0 and "__new_site_hour_usage"."failed_calls" >= 0 and "__new_site_hour_usage"."total_tokens" >= 0 and "__new_site_hour_usage"."total_summary_spend" >= 0 and "__new_site_hour_usage"."total_site_spend" >= 0 and "__new_site_hour_usage"."total_latency_ms" >= 0 and "__new_site_hour_usage"."latency_count" >= 0) +); +--> statement-breakpoint +INSERT INTO `__new_site_hour_usage`("id", "bucket_start_utc", "site_id", "total_calls", "success_calls", "failed_calls", "total_tokens", "total_summary_spend", "total_site_spend", "total_latency_ms", "latency_count", "created_at", "updated_at") SELECT "id", "bucket_start_utc", "site_id", "total_calls", "success_calls", "failed_calls", "total_tokens", "total_summary_spend", "total_site_spend", "total_latency_ms", "latency_count", "created_at", "updated_at" FROM `site_hour_usage`;--> statement-breakpoint +DROP TABLE `site_hour_usage`;--> statement-breakpoint +ALTER TABLE `__new_site_hour_usage` RENAME TO `site_hour_usage`;--> statement-breakpoint +CREATE UNIQUE INDEX `site_hour_usage_hour_site_unique` ON `site_hour_usage` (`bucket_start_utc`,`site_id`);--> statement-breakpoint +CREATE INDEX `site_hour_usage_hour_idx` ON `site_hour_usage` (`bucket_start_utc`);--> statement-breakpoint +CREATE INDEX `site_hour_usage_site_id_idx` ON `site_hour_usage` (`site_id`); \ No newline at end of file diff --git a/drizzle/meta/0021_snapshot.json b/drizzle/meta/0021_snapshot.json index e466f5f..5d0adba 100644 --- a/drizzle/meta/0021_snapshot.json +++ b/drizzle/meta/0021_snapshot.json @@ -1,8 +1,8 @@ { "version": "6", "dialect": "sqlite", - "id": "b486744a-7f0c-4e5d-8e62-496f0a7a2ae6", - "prevId": "acb4042f-d8bc-4081-8866-4701e9e16fa4", + "id": "7692286e-983c-4375-93b7-d9289ac5a7f0", + "prevId": "b486744a-7f0c-4e5d-8e62-496f0a7a2ae6", "tables": { "account_tokens": { "name": "account_tokens", @@ -361,6 +361,104 @@ "uniqueConstraints": {}, "checkConstraints": {} }, + "admin_snapshots": { + "name": "admin_snapshots", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "namespace": { + "name": "namespace", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "snapshot_key": { + "name": "snapshot_key", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "payload": { + "name": "payload", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "generated_at": { + "name": "generated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "stale_until": { + "name": "stale_until", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "admin_snapshots_namespace_key_unique": { + "name": "admin_snapshots_namespace_key_unique", + "columns": [ + "namespace", + "snapshot_key" + ], + "isUnique": true + }, + "admin_snapshots_expires_at_idx": { + "name": "admin_snapshots_expires_at_idx", + "columns": [ + "expires_at" + ], + "isUnique": false + }, + "admin_snapshots_stale_until_idx": { + "name": "admin_snapshots_stale_until_idx", + "columns": [ + "stale_until" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, "checkin_logs": { "name": "checkin_logs", "columns": { @@ -3089,4 +3187,4 @@ "internal": { "indexes": {} } -} +} \ No newline at end of file diff --git a/drizzle/meta/0023_snapshot.json b/drizzle/meta/0023_snapshot.json new file mode 100644 index 0000000..9499843 --- /dev/null +++ b/drizzle/meta/0023_snapshot.json @@ -0,0 +1,3761 @@ +{ + "version": "6", + "dialect": "sqlite", + "id": "d584f431-0d84-4a66-96c4-a5dd8d901069", + "prevId": "7692286e-983c-4375-93b7-d9289ac5a7f0", + "tables": { + "account_tokens": { + "name": "account_tokens", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "account_id": { + "name": "account_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "token_group": { + "name": "token_group", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "value_status": { + "name": "value_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'ready'" + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'manual'" + }, + "enabled": { + "name": "enabled", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": true + }, + "is_default": { + "name": "is_default", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "account_tokens_account_id_idx": { + "name": "account_tokens_account_id_idx", + "columns": [ + "account_id" + ], + "isUnique": false + }, + "account_tokens_account_enabled_idx": { + "name": "account_tokens_account_enabled_idx", + "columns": [ + "account_id", + "enabled" + ], + "isUnique": false + }, + "account_tokens_enabled_idx": { + "name": "account_tokens_enabled_idx", + "columns": [ + "enabled" + ], + "isUnique": false + } + }, + "foreignKeys": { + "account_tokens_account_id_accounts_id_fk": { + "name": "account_tokens_account_id_accounts_id_fk", + "tableFrom": "account_tokens", + "tableTo": "accounts", + "columnsFrom": [ + "account_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "accounts": { + "name": "accounts", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "site_id": { + "name": "site_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "api_token": { + "name": "api_token", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "balance": { + "name": "balance", + "type": "real", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "balance_used": { + "name": "balance_used", + "type": "real", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "quota": { + "name": "quota", + "type": "real", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "unit_cost": { + "name": "unit_cost", + "type": "real", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "value_score": { + "name": "value_score", + "type": "real", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'active'" + }, + "is_pinned": { + "name": "is_pinned", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": false + }, + "sort_order": { + "name": "sort_order", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "checkin_enabled": { + "name": "checkin_enabled", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": true + }, + "last_checkin_at": { + "name": "last_checkin_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_balance_refresh": { + "name": "last_balance_refresh", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "oauth_provider": { + "name": "oauth_provider", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "oauth_account_key": { + "name": "oauth_account_key", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "oauth_project_id": { + "name": "oauth_project_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "extra_config": { + "name": "extra_config", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "accounts_site_id_idx": { + "name": "accounts_site_id_idx", + "columns": [ + "site_id" + ], + "isUnique": false + }, + "accounts_status_idx": { + "name": "accounts_status_idx", + "columns": [ + "status" + ], + "isUnique": false + }, + "accounts_site_status_idx": { + "name": "accounts_site_status_idx", + "columns": [ + "site_id", + "status" + ], + "isUnique": false + }, + "accounts_oauth_provider_idx": { + "name": "accounts_oauth_provider_idx", + "columns": [ + "oauth_provider" + ], + "isUnique": false + }, + "accounts_oauth_identity_idx": { + "name": "accounts_oauth_identity_idx", + "columns": [ + "oauth_provider", + "oauth_account_key", + "oauth_project_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "accounts_site_id_sites_id_fk": { + "name": "accounts_site_id_sites_id_fk", + "tableFrom": "accounts", + "tableTo": "sites", + "columnsFrom": [ + "site_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "admin_snapshots": { + "name": "admin_snapshots", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "namespace": { + "name": "namespace", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "snapshot_key": { + "name": "snapshot_key", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "payload": { + "name": "payload", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "generated_at": { + "name": "generated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "stale_until": { + "name": "stale_until", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "admin_snapshots_namespace_key_unique": { + "name": "admin_snapshots_namespace_key_unique", + "columns": [ + "namespace", + "snapshot_key" + ], + "isUnique": true + }, + "admin_snapshots_expires_at_idx": { + "name": "admin_snapshots_expires_at_idx", + "columns": [ + "expires_at" + ], + "isUnique": false + }, + "admin_snapshots_stale_until_idx": { + "name": "admin_snapshots_stale_until_idx", + "columns": [ + "stale_until" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "analytics_projection_checkpoints": { + "name": "analytics_projection_checkpoints", + "columns": { + "projector_key": { + "name": "projector_key", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "time_zone": { + "name": "time_zone", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'Local'" + }, + "last_proxy_log_id": { + "name": "last_proxy_log_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "watermark_created_at": { + "name": "watermark_created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "recompute_from_id": { + "name": "recompute_from_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "recompute_requested_at": { + "name": "recompute_requested_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "recompute_reason": { + "name": "recompute_reason", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "recompute_started_at": { + "name": "recompute_started_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "recompute_completed_at": { + "name": "recompute_completed_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_projected_at": { + "name": "last_projected_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_successful_at": { + "name": "last_successful_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_error": { + "name": "last_error", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "analytics_projection_checkpoints_recompute_from_id_idx": { + "name": "analytics_projection_checkpoints_recompute_from_id_idx", + "columns": [ + "recompute_from_id" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "checkin_logs": { + "name": "checkin_logs", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "account_id": { + "name": "account_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "message": { + "name": "message", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "reward": { + "name": "reward", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "checkin_logs_account_created_at_idx": { + "name": "checkin_logs_account_created_at_idx", + "columns": [ + "account_id", + "created_at" + ], + "isUnique": false + }, + "checkin_logs_created_at_idx": { + "name": "checkin_logs_created_at_idx", + "columns": [ + "created_at" + ], + "isUnique": false + }, + "checkin_logs_status_idx": { + "name": "checkin_logs_status_idx", + "columns": [ + "status" + ], + "isUnique": false + } + }, + "foreignKeys": { + "checkin_logs_account_id_accounts_id_fk": { + "name": "checkin_logs_account_id_accounts_id_fk", + "tableFrom": "checkin_logs", + "tableTo": "accounts", + "columnsFrom": [ + "account_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "downstream_api_keys": { + "name": "downstream_api_keys", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "group_name": { + "name": "group_name", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "tags": { + "name": "tags", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "enabled": { + "name": "enabled", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": true + }, + "expires_at": { + "name": "expires_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "max_cost": { + "name": "max_cost", + "type": "real", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "used_cost": { + "name": "used_cost", + "type": "real", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "max_requests": { + "name": "max_requests", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "used_requests": { + "name": "used_requests", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "supported_models": { + "name": "supported_models", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "allowed_route_ids": { + "name": "allowed_route_ids", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "site_weight_multipliers": { + "name": "site_weight_multipliers", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "excluded_site_ids": { + "name": "excluded_site_ids", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "excluded_credential_refs": { + "name": "excluded_credential_refs", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_used_at": { + "name": "last_used_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "downstream_api_keys_key_unique": { + "name": "downstream_api_keys_key_unique", + "columns": [ + "key" + ], + "isUnique": true + }, + "downstream_api_keys_name_idx": { + "name": "downstream_api_keys_name_idx", + "columns": [ + "name" + ], + "isUnique": false + }, + "downstream_api_keys_enabled_idx": { + "name": "downstream_api_keys_enabled_idx", + "columns": [ + "enabled" + ], + "isUnique": false + }, + "downstream_api_keys_expires_at_idx": { + "name": "downstream_api_keys_expires_at_idx", + "columns": [ + "expires_at" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "events": { + "name": "events", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "message": { + "name": "message", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "level": { + "name": "level", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'info'" + }, + "read": { + "name": "read", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": false + }, + "related_id": { + "name": "related_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "related_type": { + "name": "related_type", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "events_read_created_at_idx": { + "name": "events_read_created_at_idx", + "columns": [ + "read", + "created_at" + ], + "isUnique": false + }, + "events_type_created_at_idx": { + "name": "events_type_created_at_idx", + "columns": [ + "type", + "created_at" + ], + "isUnique": false + }, + "events_created_at_idx": { + "name": "events_created_at_idx", + "columns": [ + "created_at" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "model_availability": { + "name": "model_availability", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "account_id": { + "name": "account_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "model_name": { + "name": "model_name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "available": { + "name": "available", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "is_manual": { + "name": "is_manual", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": false + }, + "latency_ms": { + "name": "latency_ms", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "checked_at": { + "name": "checked_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "model_availability_account_model_unique": { + "name": "model_availability_account_model_unique", + "columns": [ + "account_id", + "model_name" + ], + "isUnique": true + }, + "model_availability_account_available_idx": { + "name": "model_availability_account_available_idx", + "columns": [ + "account_id", + "available" + ], + "isUnique": false + }, + "model_availability_model_name_idx": { + "name": "model_availability_model_name_idx", + "columns": [ + "model_name" + ], + "isUnique": false + } + }, + "foreignKeys": { + "model_availability_account_id_accounts_id_fk": { + "name": "model_availability_account_id_accounts_id_fk", + "tableFrom": "model_availability", + "tableTo": "accounts", + "columnsFrom": [ + "account_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "model_day_usage": { + "name": "model_day_usage", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "local_day": { + "name": "local_day", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "site_id": { + "name": "site_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "total_calls": { + "name": "total_calls", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "success_calls": { + "name": "success_calls", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "failed_calls": { + "name": "failed_calls", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "total_tokens": { + "name": "total_tokens", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "total_spend": { + "name": "total_spend", + "type": "real", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "total_latency_ms": { + "name": "total_latency_ms", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "latency_count": { + "name": "latency_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "model_day_usage_day_site_model_unique": { + "name": "model_day_usage_day_site_model_unique", + "columns": [ + "local_day", + "site_id", + "model" + ], + "isUnique": true + }, + "model_day_usage_day_idx": { + "name": "model_day_usage_day_idx", + "columns": [ + "local_day" + ], + "isUnique": false + }, + "model_day_usage_site_id_idx": { + "name": "model_day_usage_site_id_idx", + "columns": [ + "site_id" + ], + "isUnique": false + }, + "model_day_usage_model_idx": { + "name": "model_day_usage_model_idx", + "columns": [ + "model" + ], + "isUnique": false + } + }, + "foreignKeys": { + "model_day_usage_site_id_sites_id_fk": { + "name": "model_day_usage_site_id_sites_id_fk", + "tableFrom": "model_day_usage", + "tableTo": "sites", + "columnsFrom": [ + "site_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "oauth_route_unit_members": { + "name": "oauth_route_unit_members", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "unit_id": { + "name": "unit_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "account_id": { + "name": "account_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "sort_order": { + "name": "sort_order", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "success_count": { + "name": "success_count", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "fail_count": { + "name": "fail_count", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "total_latency_ms": { + "name": "total_latency_ms", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "total_cost": { + "name": "total_cost", + "type": "real", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "last_used_at": { + "name": "last_used_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_selected_at": { + "name": "last_selected_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_fail_at": { + "name": "last_fail_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "consecutive_fail_count": { + "name": "consecutive_fail_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "cooldown_level": { + "name": "cooldown_level", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "cooldown_until": { + "name": "cooldown_until", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "oauth_route_unit_members_unit_account_unique": { + "name": "oauth_route_unit_members_unit_account_unique", + "columns": [ + "unit_id", + "account_id" + ], + "isUnique": true + }, + "oauth_route_unit_members_account_unique": { + "name": "oauth_route_unit_members_account_unique", + "columns": [ + "account_id" + ], + "isUnique": true + }, + "oauth_route_unit_members_unit_sort_idx": { + "name": "oauth_route_unit_members_unit_sort_idx", + "columns": [ + "unit_id", + "sort_order" + ], + "isUnique": false + }, + "oauth_route_unit_members_unit_cooldown_idx": { + "name": "oauth_route_unit_members_unit_cooldown_idx", + "columns": [ + "unit_id", + "cooldown_until" + ], + "isUnique": false + } + }, + "foreignKeys": { + "oauth_route_unit_members_unit_id_oauth_route_units_id_fk": { + "name": "oauth_route_unit_members_unit_id_oauth_route_units_id_fk", + "tableFrom": "oauth_route_unit_members", + "tableTo": "oauth_route_units", + "columnsFrom": [ + "unit_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "oauth_route_unit_members_account_id_accounts_id_fk": { + "name": "oauth_route_unit_members_account_id_accounts_id_fk", + "tableFrom": "oauth_route_unit_members", + "tableTo": "accounts", + "columnsFrom": [ + "account_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "oauth_route_units": { + "name": "oauth_route_units", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "site_id": { + "name": "site_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "strategy": { + "name": "strategy", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'round_robin'" + }, + "enabled": { + "name": "enabled", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "oauth_route_units_site_provider_idx": { + "name": "oauth_route_units_site_provider_idx", + "columns": [ + "site_id", + "provider" + ], + "isUnique": false + }, + "oauth_route_units_enabled_idx": { + "name": "oauth_route_units_enabled_idx", + "columns": [ + "enabled" + ], + "isUnique": false + } + }, + "foreignKeys": { + "oauth_route_units_site_id_sites_id_fk": { + "name": "oauth_route_units_site_id_sites_id_fk", + "tableFrom": "oauth_route_units", + "tableTo": "sites", + "columnsFrom": [ + "site_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "proxy_debug_attempts": { + "name": "proxy_debug_attempts", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "trace_id": { + "name": "trace_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "attempt_index": { + "name": "attempt_index", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "endpoint": { + "name": "endpoint", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "request_path": { + "name": "request_path", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "target_url": { + "name": "target_url", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "runtime_executor": { + "name": "runtime_executor", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "request_headers_json": { + "name": "request_headers_json", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "request_body_json": { + "name": "request_body_json", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "response_status": { + "name": "response_status", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "response_headers_json": { + "name": "response_headers_json", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "response_body_json": { + "name": "response_body_json", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "raw_error_text": { + "name": "raw_error_text", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "recover_applied": { + "name": "recover_applied", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": false + }, + "downgrade_decision": { + "name": "downgrade_decision", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": false + }, + "downgrade_reason": { + "name": "downgrade_reason", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "memory_write_json": { + "name": "memory_write_json", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "proxy_debug_attempts_trace_attempt_unique": { + "name": "proxy_debug_attempts_trace_attempt_unique", + "columns": [ + "trace_id", + "attempt_index" + ], + "isUnique": true + }, + "proxy_debug_attempts_trace_created_at_idx": { + "name": "proxy_debug_attempts_trace_created_at_idx", + "columns": [ + "trace_id", + "created_at" + ], + "isUnique": false + } + }, + "foreignKeys": { + "proxy_debug_attempts_trace_id_proxy_debug_traces_id_fk": { + "name": "proxy_debug_attempts_trace_id_proxy_debug_traces_id_fk", + "tableFrom": "proxy_debug_attempts", + "tableTo": "proxy_debug_traces", + "columnsFrom": [ + "trace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "proxy_debug_traces": { + "name": "proxy_debug_traces", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "downstream_path": { + "name": "downstream_path", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "client_kind": { + "name": "client_kind", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "session_id": { + "name": "session_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "trace_hint": { + "name": "trace_hint", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "requested_model": { + "name": "requested_model", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "downstream_api_key_id": { + "name": "downstream_api_key_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "request_headers_json": { + "name": "request_headers_json", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "request_body_json": { + "name": "request_body_json", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "sticky_session_key": { + "name": "sticky_session_key", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "sticky_hit_channel_id": { + "name": "sticky_hit_channel_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "selected_channel_id": { + "name": "selected_channel_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "selected_route_id": { + "name": "selected_route_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "selected_account_id": { + "name": "selected_account_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "selected_site_id": { + "name": "selected_site_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "selected_site_platform": { + "name": "selected_site_platform", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "endpoint_candidates_json": { + "name": "endpoint_candidates_json", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "endpoint_runtime_state_json": { + "name": "endpoint_runtime_state_json", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "decision_summary_json": { + "name": "decision_summary_json", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "final_status": { + "name": "final_status", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "final_http_status": { + "name": "final_http_status", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "final_upstream_path": { + "name": "final_upstream_path", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "final_response_headers_json": { + "name": "final_response_headers_json", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "final_response_body_json": { + "name": "final_response_body_json", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "proxy_debug_traces_created_at_idx": { + "name": "proxy_debug_traces_created_at_idx", + "columns": [ + "created_at" + ], + "isUnique": false + }, + "proxy_debug_traces_session_created_at_idx": { + "name": "proxy_debug_traces_session_created_at_idx", + "columns": [ + "session_id", + "created_at" + ], + "isUnique": false + }, + "proxy_debug_traces_model_created_at_idx": { + "name": "proxy_debug_traces_model_created_at_idx", + "columns": [ + "requested_model", + "created_at" + ], + "isUnique": false + }, + "proxy_debug_traces_final_status_created_at_idx": { + "name": "proxy_debug_traces_final_status_created_at_idx", + "columns": [ + "final_status", + "created_at" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "proxy_files": { + "name": "proxy_files", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "public_id": { + "name": "public_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "owner_type": { + "name": "owner_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "owner_id": { + "name": "owner_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "filename": { + "name": "filename", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "mime_type": { + "name": "mime_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "purpose": { + "name": "purpose", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "byte_size": { + "name": "byte_size", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "sha256": { + "name": "sha256", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "content_base64": { + "name": "content_base64", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "deleted_at": { + "name": "deleted_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "proxy_files_public_id_unique": { + "name": "proxy_files_public_id_unique", + "columns": [ + "public_id" + ], + "isUnique": true + }, + "proxy_files_owner_lookup_idx": { + "name": "proxy_files_owner_lookup_idx", + "columns": [ + "owner_type", + "owner_id", + "deleted_at" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "proxy_logs": { + "name": "proxy_logs", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "route_id": { + "name": "route_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "channel_id": { + "name": "channel_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "account_id": { + "name": "account_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "downstream_api_key_id": { + "name": "downstream_api_key_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "model_requested": { + "name": "model_requested", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "model_actual": { + "name": "model_actual", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "http_status": { + "name": "http_status", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "is_stream": { + "name": "is_stream", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "first_byte_latency_ms": { + "name": "first_byte_latency_ms", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "latency_ms": { + "name": "latency_ms", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "prompt_tokens": { + "name": "prompt_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "completion_tokens": { + "name": "completion_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "total_tokens": { + "name": "total_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "estimated_cost": { + "name": "estimated_cost", + "type": "real", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "billing_details": { + "name": "billing_details", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "client_family": { + "name": "client_family", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "client_app_id": { + "name": "client_app_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "client_app_name": { + "name": "client_app_name", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "client_confidence": { + "name": "client_confidence", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "retry_count": { + "name": "retry_count", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "proxy_logs_created_at_idx": { + "name": "proxy_logs_created_at_idx", + "columns": [ + "created_at" + ], + "isUnique": false + }, + "proxy_logs_account_created_at_idx": { + "name": "proxy_logs_account_created_at_idx", + "columns": [ + "account_id", + "created_at" + ], + "isUnique": false + }, + "proxy_logs_status_created_at_idx": { + "name": "proxy_logs_status_created_at_idx", + "columns": [ + "status", + "created_at" + ], + "isUnique": false + }, + "proxy_logs_model_actual_created_at_idx": { + "name": "proxy_logs_model_actual_created_at_idx", + "columns": [ + "model_actual", + "created_at" + ], + "isUnique": false + }, + "proxy_logs_downstream_api_key_created_at_idx": { + "name": "proxy_logs_downstream_api_key_created_at_idx", + "columns": [ + "downstream_api_key_id", + "created_at" + ], + "isUnique": false + }, + "proxy_logs_client_app_id_created_at_idx": { + "name": "proxy_logs_client_app_id_created_at_idx", + "columns": [ + "client_app_id", + "created_at" + ], + "isUnique": false + }, + "proxy_logs_client_family_created_at_idx": { + "name": "proxy_logs_client_family_created_at_idx", + "columns": [ + "client_family", + "created_at" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "proxy_video_tasks": { + "name": "proxy_video_tasks", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "public_id": { + "name": "public_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "upstream_video_id": { + "name": "upstream_video_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "site_url": { + "name": "site_url", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "token_value": { + "name": "token_value", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "requested_model": { + "name": "requested_model", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "actual_model": { + "name": "actual_model", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "channel_id": { + "name": "channel_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "account_id": { + "name": "account_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "status_snapshot": { + "name": "status_snapshot", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "upstream_response_meta": { + "name": "upstream_response_meta", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_upstream_status": { + "name": "last_upstream_status", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_polled_at": { + "name": "last_polled_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "proxy_video_tasks_public_id_unique": { + "name": "proxy_video_tasks_public_id_unique", + "columns": [ + "public_id" + ], + "isUnique": true + }, + "proxy_video_tasks_upstream_video_id_idx": { + "name": "proxy_video_tasks_upstream_video_id_idx", + "columns": [ + "upstream_video_id" + ], + "isUnique": false + }, + "proxy_video_tasks_created_at_idx": { + "name": "proxy_video_tasks_created_at_idx", + "columns": [ + "created_at" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "route_channels": { + "name": "route_channels", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "route_id": { + "name": "route_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "account_id": { + "name": "account_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "token_id": { + "name": "token_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "oauth_route_unit_id": { + "name": "oauth_route_unit_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "source_model": { + "name": "source_model", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "priority": { + "name": "priority", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "weight": { + "name": "weight", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 10 + }, + "enabled": { + "name": "enabled", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": true + }, + "manual_override": { + "name": "manual_override", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": false + }, + "success_count": { + "name": "success_count", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "fail_count": { + "name": "fail_count", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "total_latency_ms": { + "name": "total_latency_ms", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "total_cost": { + "name": "total_cost", + "type": "real", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "last_used_at": { + "name": "last_used_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_selected_at": { + "name": "last_selected_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_fail_at": { + "name": "last_fail_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "consecutive_fail_count": { + "name": "consecutive_fail_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "cooldown_level": { + "name": "cooldown_level", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "cooldown_until": { + "name": "cooldown_until", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "route_channels_route_id_idx": { + "name": "route_channels_route_id_idx", + "columns": [ + "route_id" + ], + "isUnique": false + }, + "route_channels_account_id_idx": { + "name": "route_channels_account_id_idx", + "columns": [ + "account_id" + ], + "isUnique": false + }, + "route_channels_token_id_idx": { + "name": "route_channels_token_id_idx", + "columns": [ + "token_id" + ], + "isUnique": false + }, + "route_channels_oauth_route_unit_id_idx": { + "name": "route_channels_oauth_route_unit_id_idx", + "columns": [ + "oauth_route_unit_id" + ], + "isUnique": false + }, + "route_channels_route_enabled_idx": { + "name": "route_channels_route_enabled_idx", + "columns": [ + "route_id", + "enabled" + ], + "isUnique": false + }, + "route_channels_route_token_idx": { + "name": "route_channels_route_token_idx", + "columns": [ + "route_id", + "token_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "route_channels_route_id_token_routes_id_fk": { + "name": "route_channels_route_id_token_routes_id_fk", + "tableFrom": "route_channels", + "tableTo": "token_routes", + "columnsFrom": [ + "route_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "route_channels_account_id_accounts_id_fk": { + "name": "route_channels_account_id_accounts_id_fk", + "tableFrom": "route_channels", + "tableTo": "accounts", + "columnsFrom": [ + "account_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "route_channels_token_id_account_tokens_id_fk": { + "name": "route_channels_token_id_account_tokens_id_fk", + "tableFrom": "route_channels", + "tableTo": "account_tokens", + "columnsFrom": [ + "token_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "route_group_sources": { + "name": "route_group_sources", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "group_route_id": { + "name": "group_route_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "source_route_id": { + "name": "source_route_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "route_group_sources_group_source_unique": { + "name": "route_group_sources_group_source_unique", + "columns": [ + "group_route_id", + "source_route_id" + ], + "isUnique": true + }, + "route_group_sources_source_route_id_idx": { + "name": "route_group_sources_source_route_id_idx", + "columns": [ + "source_route_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "route_group_sources_group_route_id_token_routes_id_fk": { + "name": "route_group_sources_group_route_id_token_routes_id_fk", + "tableFrom": "route_group_sources", + "tableTo": "token_routes", + "columnsFrom": [ + "group_route_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "route_group_sources_source_route_id_token_routes_id_fk": { + "name": "route_group_sources_source_route_id_token_routes_id_fk", + "tableFrom": "route_group_sources", + "tableTo": "token_routes", + "columnsFrom": [ + "source_route_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "settings": { + "name": "settings", + "columns": { + "key": { + "name": "key", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "site_announcements": { + "name": "site_announcements", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "site_id": { + "name": "site_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "platform": { + "name": "platform", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "source_key": { + "name": "source_key", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "level": { + "name": "level", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'info'" + }, + "source_url": { + "name": "source_url", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "starts_at": { + "name": "starts_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "ends_at": { + "name": "ends_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "upstream_created_at": { + "name": "upstream_created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "upstream_updated_at": { + "name": "upstream_updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "first_seen_at": { + "name": "first_seen_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "last_seen_at": { + "name": "last_seen_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "read_at": { + "name": "read_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "dismissed_at": { + "name": "dismissed_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "raw_payload": { + "name": "raw_payload", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "site_announcements_site_source_key_unique": { + "name": "site_announcements_site_source_key_unique", + "columns": [ + "site_id", + "source_key" + ], + "isUnique": true + }, + "site_announcements_site_id_first_seen_at_idx": { + "name": "site_announcements_site_id_first_seen_at_idx", + "columns": [ + "site_id", + "first_seen_at" + ], + "isUnique": false + }, + "site_announcements_read_at_idx": { + "name": "site_announcements_read_at_idx", + "columns": [ + "read_at" + ], + "isUnique": false + } + }, + "foreignKeys": { + "site_announcements_site_id_sites_id_fk": { + "name": "site_announcements_site_id_sites_id_fk", + "tableFrom": "site_announcements", + "tableTo": "sites", + "columnsFrom": [ + "site_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "site_api_endpoints": { + "name": "site_api_endpoints", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "site_id": { + "name": "site_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "url": { + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "enabled": { + "name": "enabled", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": true + }, + "sort_order": { + "name": "sort_order", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "cooldown_until": { + "name": "cooldown_until", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_selected_at": { + "name": "last_selected_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_failed_at": { + "name": "last_failed_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_failure_reason": { + "name": "last_failure_reason", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "site_api_endpoints_site_url_unique": { + "name": "site_api_endpoints_site_url_unique", + "columns": [ + "site_id", + "url" + ], + "isUnique": true + }, + "site_api_endpoints_site_enabled_sort_idx": { + "name": "site_api_endpoints_site_enabled_sort_idx", + "columns": [ + "site_id", + "enabled", + "sort_order" + ], + "isUnique": false + }, + "site_api_endpoints_site_cooldown_idx": { + "name": "site_api_endpoints_site_cooldown_idx", + "columns": [ + "site_id", + "cooldown_until" + ], + "isUnique": false + } + }, + "foreignKeys": { + "site_api_endpoints_site_id_sites_id_fk": { + "name": "site_api_endpoints_site_id_sites_id_fk", + "tableFrom": "site_api_endpoints", + "tableTo": "sites", + "columnsFrom": [ + "site_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "site_day_usage": { + "name": "site_day_usage", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "local_day": { + "name": "local_day", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "site_id": { + "name": "site_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "total_calls": { + "name": "total_calls", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "success_calls": { + "name": "success_calls", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "failed_calls": { + "name": "failed_calls", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "total_tokens": { + "name": "total_tokens", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "total_summary_spend": { + "name": "total_summary_spend", + "type": "real", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "total_site_spend": { + "name": "total_site_spend", + "type": "real", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "total_latency_ms": { + "name": "total_latency_ms", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "latency_count": { + "name": "latency_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "site_day_usage_day_site_unique": { + "name": "site_day_usage_day_site_unique", + "columns": [ + "local_day", + "site_id" + ], + "isUnique": true + }, + "site_day_usage_day_idx": { + "name": "site_day_usage_day_idx", + "columns": [ + "local_day" + ], + "isUnique": false + }, + "site_day_usage_site_id_idx": { + "name": "site_day_usage_site_id_idx", + "columns": [ + "site_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "site_day_usage_site_id_sites_id_fk": { + "name": "site_day_usage_site_id_sites_id_fk", + "tableFrom": "site_day_usage", + "tableTo": "sites", + "columnsFrom": [ + "site_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "site_disabled_models": { + "name": "site_disabled_models", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "site_id": { + "name": "site_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "model_name": { + "name": "model_name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "site_disabled_models_site_model_unique": { + "name": "site_disabled_models_site_model_unique", + "columns": [ + "site_id", + "model_name" + ], + "isUnique": true + }, + "site_disabled_models_site_id_idx": { + "name": "site_disabled_models_site_id_idx", + "columns": [ + "site_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "site_disabled_models_site_id_sites_id_fk": { + "name": "site_disabled_models_site_id_sites_id_fk", + "tableFrom": "site_disabled_models", + "tableTo": "sites", + "columnsFrom": [ + "site_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "site_hour_usage": { + "name": "site_hour_usage", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "bucket_start_utc": { + "name": "bucket_start_utc", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "site_id": { + "name": "site_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "total_calls": { + "name": "total_calls", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "success_calls": { + "name": "success_calls", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "failed_calls": { + "name": "failed_calls", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "total_tokens": { + "name": "total_tokens", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "total_summary_spend": { + "name": "total_summary_spend", + "type": "real", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "total_site_spend": { + "name": "total_site_spend", + "type": "real", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "total_latency_ms": { + "name": "total_latency_ms", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "latency_count": { + "name": "latency_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "site_hour_usage_hour_site_unique": { + "name": "site_hour_usage_hour_site_unique", + "columns": [ + "bucket_start_utc", + "site_id" + ], + "isUnique": true + }, + "site_hour_usage_hour_idx": { + "name": "site_hour_usage_hour_idx", + "columns": [ + "bucket_start_utc" + ], + "isUnique": false + }, + "site_hour_usage_site_id_idx": { + "name": "site_hour_usage_site_id_idx", + "columns": [ + "site_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "site_hour_usage_site_id_sites_id_fk": { + "name": "site_hour_usage_site_id_sites_id_fk", + "tableFrom": "site_hour_usage", + "tableTo": "sites", + "columnsFrom": [ + "site_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "sites": { + "name": "sites", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "url": { + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "external_checkin_url": { + "name": "external_checkin_url", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "platform": { + "name": "platform", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "proxy_url": { + "name": "proxy_url", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "use_system_proxy": { + "name": "use_system_proxy", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": false + }, + "custom_headers": { + "name": "custom_headers", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'active'" + }, + "is_pinned": { + "name": "is_pinned", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": false + }, + "sort_order": { + "name": "sort_order", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "global_weight": { + "name": "global_weight", + "type": "real", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 1 + }, + "api_key": { + "name": "api_key", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "sites_status_idx": { + "name": "sites_status_idx", + "columns": [ + "status" + ], + "isUnique": false + }, + "sites_platform_url_unique": { + "name": "sites_platform_url_unique", + "columns": [ + "platform", + "url" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "token_model_availability": { + "name": "token_model_availability", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "token_id": { + "name": "token_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "model_name": { + "name": "model_name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "available": { + "name": "available", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "latency_ms": { + "name": "latency_ms", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "checked_at": { + "name": "checked_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "token_model_availability_token_model_unique": { + "name": "token_model_availability_token_model_unique", + "columns": [ + "token_id", + "model_name" + ], + "isUnique": true + }, + "token_model_availability_token_available_idx": { + "name": "token_model_availability_token_available_idx", + "columns": [ + "token_id", + "available" + ], + "isUnique": false + }, + "token_model_availability_model_name_idx": { + "name": "token_model_availability_model_name_idx", + "columns": [ + "model_name" + ], + "isUnique": false + }, + "token_model_availability_available_idx": { + "name": "token_model_availability_available_idx", + "columns": [ + "available" + ], + "isUnique": false + } + }, + "foreignKeys": { + "token_model_availability_token_id_account_tokens_id_fk": { + "name": "token_model_availability_token_id_account_tokens_id_fk", + "tableFrom": "token_model_availability", + "tableTo": "account_tokens", + "columnsFrom": [ + "token_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "token_routes": { + "name": "token_routes", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "model_pattern": { + "name": "model_pattern", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "display_name": { + "name": "display_name", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "display_icon": { + "name": "display_icon", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "route_mode": { + "name": "route_mode", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'pattern'" + }, + "model_mapping": { + "name": "model_mapping", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "decision_snapshot": { + "name": "decision_snapshot", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "decision_refreshed_at": { + "name": "decision_refreshed_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "routing_strategy": { + "name": "routing_strategy", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'weighted'" + }, + "enabled": { + "name": "enabled", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "token_routes_model_pattern_idx": { + "name": "token_routes_model_pattern_idx", + "columns": [ + "model_pattern" + ], + "isUnique": false + }, + "token_routes_enabled_idx": { + "name": "token_routes_enabled_idx", + "columns": [ + "enabled" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + } + }, + "views": {}, + "enums": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + }, + "internal": { + "indexes": {} + } +} \ No newline at end of file diff --git a/drizzle/meta/0024_snapshot.json b/drizzle/meta/0024_snapshot.json new file mode 100644 index 0000000..63a0e56 --- /dev/null +++ b/drizzle/meta/0024_snapshot.json @@ -0,0 +1,3804 @@ +{ + "version": "6", + "dialect": "sqlite", + "id": "11d634a1-669e-44c0-bc53-f60e7a1452cf", + "prevId": "d584f431-0d84-4a66-96c4-a5dd8d901069", + "tables": { + "account_tokens": { + "name": "account_tokens", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "account_id": { + "name": "account_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "token_group": { + "name": "token_group", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "value_status": { + "name": "value_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'ready'" + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'manual'" + }, + "enabled": { + "name": "enabled", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": true + }, + "is_default": { + "name": "is_default", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "account_tokens_account_id_idx": { + "name": "account_tokens_account_id_idx", + "columns": [ + "account_id" + ], + "isUnique": false + }, + "account_tokens_account_enabled_idx": { + "name": "account_tokens_account_enabled_idx", + "columns": [ + "account_id", + "enabled" + ], + "isUnique": false + }, + "account_tokens_enabled_idx": { + "name": "account_tokens_enabled_idx", + "columns": [ + "enabled" + ], + "isUnique": false + } + }, + "foreignKeys": { + "account_tokens_account_id_accounts_id_fk": { + "name": "account_tokens_account_id_accounts_id_fk", + "tableFrom": "account_tokens", + "tableTo": "accounts", + "columnsFrom": [ + "account_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "accounts": { + "name": "accounts", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "site_id": { + "name": "site_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "api_token": { + "name": "api_token", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "balance": { + "name": "balance", + "type": "real", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "balance_used": { + "name": "balance_used", + "type": "real", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "quota": { + "name": "quota", + "type": "real", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "unit_cost": { + "name": "unit_cost", + "type": "real", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "value_score": { + "name": "value_score", + "type": "real", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'active'" + }, + "is_pinned": { + "name": "is_pinned", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": false + }, + "sort_order": { + "name": "sort_order", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "checkin_enabled": { + "name": "checkin_enabled", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": true + }, + "last_checkin_at": { + "name": "last_checkin_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_balance_refresh": { + "name": "last_balance_refresh", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "oauth_provider": { + "name": "oauth_provider", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "oauth_account_key": { + "name": "oauth_account_key", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "oauth_project_id": { + "name": "oauth_project_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "extra_config": { + "name": "extra_config", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "accounts_site_id_idx": { + "name": "accounts_site_id_idx", + "columns": [ + "site_id" + ], + "isUnique": false + }, + "accounts_status_idx": { + "name": "accounts_status_idx", + "columns": [ + "status" + ], + "isUnique": false + }, + "accounts_site_status_idx": { + "name": "accounts_site_status_idx", + "columns": [ + "site_id", + "status" + ], + "isUnique": false + }, + "accounts_oauth_provider_idx": { + "name": "accounts_oauth_provider_idx", + "columns": [ + "oauth_provider" + ], + "isUnique": false + }, + "accounts_oauth_identity_idx": { + "name": "accounts_oauth_identity_idx", + "columns": [ + "oauth_provider", + "oauth_account_key", + "oauth_project_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "accounts_site_id_sites_id_fk": { + "name": "accounts_site_id_sites_id_fk", + "tableFrom": "accounts", + "tableTo": "sites", + "columnsFrom": [ + "site_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "admin_snapshots": { + "name": "admin_snapshots", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "namespace": { + "name": "namespace", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "snapshot_key": { + "name": "snapshot_key", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "payload": { + "name": "payload", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "generated_at": { + "name": "generated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "stale_until": { + "name": "stale_until", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "admin_snapshots_namespace_key_unique": { + "name": "admin_snapshots_namespace_key_unique", + "columns": [ + "namespace", + "snapshot_key" + ], + "isUnique": true + }, + "admin_snapshots_expires_at_idx": { + "name": "admin_snapshots_expires_at_idx", + "columns": [ + "expires_at" + ], + "isUnique": false + }, + "admin_snapshots_stale_until_idx": { + "name": "admin_snapshots_stale_until_idx", + "columns": [ + "stale_until" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "analytics_projection_checkpoints": { + "name": "analytics_projection_checkpoints", + "columns": { + "projector_key": { + "name": "projector_key", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "time_zone": { + "name": "time_zone", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'Local'" + }, + "last_proxy_log_id": { + "name": "last_proxy_log_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "watermark_created_at": { + "name": "watermark_created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "lease_owner": { + "name": "lease_owner", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "lease_token": { + "name": "lease_token", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "lease_expires_at": { + "name": "lease_expires_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "recompute_from_id": { + "name": "recompute_from_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "recompute_requested_at": { + "name": "recompute_requested_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "recompute_reason": { + "name": "recompute_reason", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "recompute_started_at": { + "name": "recompute_started_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "recompute_completed_at": { + "name": "recompute_completed_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_projected_at": { + "name": "last_projected_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_successful_at": { + "name": "last_successful_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_error": { + "name": "last_error", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "analytics_projection_checkpoints_recompute_from_id_idx": { + "name": "analytics_projection_checkpoints_recompute_from_id_idx", + "columns": [ + "recompute_from_id" + ], + "isUnique": false + }, + "analytics_projection_checkpoints_lease_expires_at_idx": { + "name": "analytics_projection_checkpoints_lease_expires_at_idx", + "columns": [ + "lease_expires_at" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "checkin_logs": { + "name": "checkin_logs", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "account_id": { + "name": "account_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "message": { + "name": "message", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "reward": { + "name": "reward", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "checkin_logs_account_created_at_idx": { + "name": "checkin_logs_account_created_at_idx", + "columns": [ + "account_id", + "created_at" + ], + "isUnique": false + }, + "checkin_logs_created_at_idx": { + "name": "checkin_logs_created_at_idx", + "columns": [ + "created_at" + ], + "isUnique": false + }, + "checkin_logs_status_idx": { + "name": "checkin_logs_status_idx", + "columns": [ + "status" + ], + "isUnique": false + } + }, + "foreignKeys": { + "checkin_logs_account_id_accounts_id_fk": { + "name": "checkin_logs_account_id_accounts_id_fk", + "tableFrom": "checkin_logs", + "tableTo": "accounts", + "columnsFrom": [ + "account_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "downstream_api_keys": { + "name": "downstream_api_keys", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "group_name": { + "name": "group_name", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "tags": { + "name": "tags", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "enabled": { + "name": "enabled", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": true + }, + "expires_at": { + "name": "expires_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "max_cost": { + "name": "max_cost", + "type": "real", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "used_cost": { + "name": "used_cost", + "type": "real", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "max_requests": { + "name": "max_requests", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "used_requests": { + "name": "used_requests", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "supported_models": { + "name": "supported_models", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "allowed_route_ids": { + "name": "allowed_route_ids", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "site_weight_multipliers": { + "name": "site_weight_multipliers", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "excluded_site_ids": { + "name": "excluded_site_ids", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "excluded_credential_refs": { + "name": "excluded_credential_refs", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_used_at": { + "name": "last_used_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "downstream_api_keys_key_unique": { + "name": "downstream_api_keys_key_unique", + "columns": [ + "key" + ], + "isUnique": true + }, + "downstream_api_keys_name_idx": { + "name": "downstream_api_keys_name_idx", + "columns": [ + "name" + ], + "isUnique": false + }, + "downstream_api_keys_enabled_idx": { + "name": "downstream_api_keys_enabled_idx", + "columns": [ + "enabled" + ], + "isUnique": false + }, + "downstream_api_keys_expires_at_idx": { + "name": "downstream_api_keys_expires_at_idx", + "columns": [ + "expires_at" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "events": { + "name": "events", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "message": { + "name": "message", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "level": { + "name": "level", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'info'" + }, + "read": { + "name": "read", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": false + }, + "related_id": { + "name": "related_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "related_type": { + "name": "related_type", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "events_read_created_at_idx": { + "name": "events_read_created_at_idx", + "columns": [ + "read", + "created_at" + ], + "isUnique": false + }, + "events_type_created_at_idx": { + "name": "events_type_created_at_idx", + "columns": [ + "type", + "created_at" + ], + "isUnique": false + }, + "events_created_at_idx": { + "name": "events_created_at_idx", + "columns": [ + "created_at" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "model_availability": { + "name": "model_availability", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "account_id": { + "name": "account_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "model_name": { + "name": "model_name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "available": { + "name": "available", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "is_manual": { + "name": "is_manual", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": false + }, + "latency_ms": { + "name": "latency_ms", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "checked_at": { + "name": "checked_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "model_availability_account_model_unique": { + "name": "model_availability_account_model_unique", + "columns": [ + "account_id", + "model_name" + ], + "isUnique": true + }, + "model_availability_account_available_idx": { + "name": "model_availability_account_available_idx", + "columns": [ + "account_id", + "available" + ], + "isUnique": false + }, + "model_availability_model_name_idx": { + "name": "model_availability_model_name_idx", + "columns": [ + "model_name" + ], + "isUnique": false + } + }, + "foreignKeys": { + "model_availability_account_id_accounts_id_fk": { + "name": "model_availability_account_id_accounts_id_fk", + "tableFrom": "model_availability", + "tableTo": "accounts", + "columnsFrom": [ + "account_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "model_day_usage": { + "name": "model_day_usage", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "local_day": { + "name": "local_day", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "site_id": { + "name": "site_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "total_calls": { + "name": "total_calls", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "success_calls": { + "name": "success_calls", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "failed_calls": { + "name": "failed_calls", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "total_tokens": { + "name": "total_tokens", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "total_spend": { + "name": "total_spend", + "type": "real", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "total_latency_ms": { + "name": "total_latency_ms", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "latency_count": { + "name": "latency_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "model_day_usage_day_site_model_unique": { + "name": "model_day_usage_day_site_model_unique", + "columns": [ + "local_day", + "site_id", + "model" + ], + "isUnique": true + }, + "model_day_usage_day_idx": { + "name": "model_day_usage_day_idx", + "columns": [ + "local_day" + ], + "isUnique": false + }, + "model_day_usage_site_id_idx": { + "name": "model_day_usage_site_id_idx", + "columns": [ + "site_id" + ], + "isUnique": false + }, + "model_day_usage_model_idx": { + "name": "model_day_usage_model_idx", + "columns": [ + "model" + ], + "isUnique": false + } + }, + "foreignKeys": { + "model_day_usage_site_id_sites_id_fk": { + "name": "model_day_usage_site_id_sites_id_fk", + "tableFrom": "model_day_usage", + "tableTo": "sites", + "columnsFrom": [ + "site_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": { + "model_day_usage_non_negative": { + "name": "model_day_usage_non_negative", + "value": "\"model_day_usage\".\"total_calls\" >= 0 and \"model_day_usage\".\"success_calls\" >= 0 and \"model_day_usage\".\"failed_calls\" >= 0 and \"model_day_usage\".\"total_tokens\" >= 0 and \"model_day_usage\".\"total_spend\" >= 0 and \"model_day_usage\".\"total_latency_ms\" >= 0 and \"model_day_usage\".\"latency_count\" >= 0" + } + } + }, + "oauth_route_unit_members": { + "name": "oauth_route_unit_members", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "unit_id": { + "name": "unit_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "account_id": { + "name": "account_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "sort_order": { + "name": "sort_order", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "success_count": { + "name": "success_count", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "fail_count": { + "name": "fail_count", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "total_latency_ms": { + "name": "total_latency_ms", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "total_cost": { + "name": "total_cost", + "type": "real", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "last_used_at": { + "name": "last_used_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_selected_at": { + "name": "last_selected_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_fail_at": { + "name": "last_fail_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "consecutive_fail_count": { + "name": "consecutive_fail_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "cooldown_level": { + "name": "cooldown_level", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "cooldown_until": { + "name": "cooldown_until", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "oauth_route_unit_members_unit_account_unique": { + "name": "oauth_route_unit_members_unit_account_unique", + "columns": [ + "unit_id", + "account_id" + ], + "isUnique": true + }, + "oauth_route_unit_members_account_unique": { + "name": "oauth_route_unit_members_account_unique", + "columns": [ + "account_id" + ], + "isUnique": true + }, + "oauth_route_unit_members_unit_sort_idx": { + "name": "oauth_route_unit_members_unit_sort_idx", + "columns": [ + "unit_id", + "sort_order" + ], + "isUnique": false + }, + "oauth_route_unit_members_unit_cooldown_idx": { + "name": "oauth_route_unit_members_unit_cooldown_idx", + "columns": [ + "unit_id", + "cooldown_until" + ], + "isUnique": false + } + }, + "foreignKeys": { + "oauth_route_unit_members_unit_id_oauth_route_units_id_fk": { + "name": "oauth_route_unit_members_unit_id_oauth_route_units_id_fk", + "tableFrom": "oauth_route_unit_members", + "tableTo": "oauth_route_units", + "columnsFrom": [ + "unit_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "oauth_route_unit_members_account_id_accounts_id_fk": { + "name": "oauth_route_unit_members_account_id_accounts_id_fk", + "tableFrom": "oauth_route_unit_members", + "tableTo": "accounts", + "columnsFrom": [ + "account_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "oauth_route_units": { + "name": "oauth_route_units", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "site_id": { + "name": "site_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "strategy": { + "name": "strategy", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'round_robin'" + }, + "enabled": { + "name": "enabled", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "oauth_route_units_site_provider_idx": { + "name": "oauth_route_units_site_provider_idx", + "columns": [ + "site_id", + "provider" + ], + "isUnique": false + }, + "oauth_route_units_enabled_idx": { + "name": "oauth_route_units_enabled_idx", + "columns": [ + "enabled" + ], + "isUnique": false + } + }, + "foreignKeys": { + "oauth_route_units_site_id_sites_id_fk": { + "name": "oauth_route_units_site_id_sites_id_fk", + "tableFrom": "oauth_route_units", + "tableTo": "sites", + "columnsFrom": [ + "site_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "proxy_debug_attempts": { + "name": "proxy_debug_attempts", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "trace_id": { + "name": "trace_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "attempt_index": { + "name": "attempt_index", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "endpoint": { + "name": "endpoint", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "request_path": { + "name": "request_path", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "target_url": { + "name": "target_url", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "runtime_executor": { + "name": "runtime_executor", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "request_headers_json": { + "name": "request_headers_json", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "request_body_json": { + "name": "request_body_json", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "response_status": { + "name": "response_status", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "response_headers_json": { + "name": "response_headers_json", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "response_body_json": { + "name": "response_body_json", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "raw_error_text": { + "name": "raw_error_text", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "recover_applied": { + "name": "recover_applied", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": false + }, + "downgrade_decision": { + "name": "downgrade_decision", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": false + }, + "downgrade_reason": { + "name": "downgrade_reason", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "memory_write_json": { + "name": "memory_write_json", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "proxy_debug_attempts_trace_attempt_unique": { + "name": "proxy_debug_attempts_trace_attempt_unique", + "columns": [ + "trace_id", + "attempt_index" + ], + "isUnique": true + }, + "proxy_debug_attempts_trace_created_at_idx": { + "name": "proxy_debug_attempts_trace_created_at_idx", + "columns": [ + "trace_id", + "created_at" + ], + "isUnique": false + } + }, + "foreignKeys": { + "proxy_debug_attempts_trace_id_proxy_debug_traces_id_fk": { + "name": "proxy_debug_attempts_trace_id_proxy_debug_traces_id_fk", + "tableFrom": "proxy_debug_attempts", + "tableTo": "proxy_debug_traces", + "columnsFrom": [ + "trace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "proxy_debug_traces": { + "name": "proxy_debug_traces", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "downstream_path": { + "name": "downstream_path", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "client_kind": { + "name": "client_kind", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "session_id": { + "name": "session_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "trace_hint": { + "name": "trace_hint", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "requested_model": { + "name": "requested_model", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "downstream_api_key_id": { + "name": "downstream_api_key_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "request_headers_json": { + "name": "request_headers_json", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "request_body_json": { + "name": "request_body_json", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "sticky_session_key": { + "name": "sticky_session_key", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "sticky_hit_channel_id": { + "name": "sticky_hit_channel_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "selected_channel_id": { + "name": "selected_channel_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "selected_route_id": { + "name": "selected_route_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "selected_account_id": { + "name": "selected_account_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "selected_site_id": { + "name": "selected_site_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "selected_site_platform": { + "name": "selected_site_platform", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "endpoint_candidates_json": { + "name": "endpoint_candidates_json", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "endpoint_runtime_state_json": { + "name": "endpoint_runtime_state_json", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "decision_summary_json": { + "name": "decision_summary_json", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "final_status": { + "name": "final_status", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "final_http_status": { + "name": "final_http_status", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "final_upstream_path": { + "name": "final_upstream_path", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "final_response_headers_json": { + "name": "final_response_headers_json", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "final_response_body_json": { + "name": "final_response_body_json", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "proxy_debug_traces_created_at_idx": { + "name": "proxy_debug_traces_created_at_idx", + "columns": [ + "created_at" + ], + "isUnique": false + }, + "proxy_debug_traces_session_created_at_idx": { + "name": "proxy_debug_traces_session_created_at_idx", + "columns": [ + "session_id", + "created_at" + ], + "isUnique": false + }, + "proxy_debug_traces_model_created_at_idx": { + "name": "proxy_debug_traces_model_created_at_idx", + "columns": [ + "requested_model", + "created_at" + ], + "isUnique": false + }, + "proxy_debug_traces_final_status_created_at_idx": { + "name": "proxy_debug_traces_final_status_created_at_idx", + "columns": [ + "final_status", + "created_at" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "proxy_files": { + "name": "proxy_files", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "public_id": { + "name": "public_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "owner_type": { + "name": "owner_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "owner_id": { + "name": "owner_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "filename": { + "name": "filename", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "mime_type": { + "name": "mime_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "purpose": { + "name": "purpose", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "byte_size": { + "name": "byte_size", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "sha256": { + "name": "sha256", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "content_base64": { + "name": "content_base64", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "deleted_at": { + "name": "deleted_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "proxy_files_public_id_unique": { + "name": "proxy_files_public_id_unique", + "columns": [ + "public_id" + ], + "isUnique": true + }, + "proxy_files_owner_lookup_idx": { + "name": "proxy_files_owner_lookup_idx", + "columns": [ + "owner_type", + "owner_id", + "deleted_at" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "proxy_logs": { + "name": "proxy_logs", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "route_id": { + "name": "route_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "channel_id": { + "name": "channel_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "account_id": { + "name": "account_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "downstream_api_key_id": { + "name": "downstream_api_key_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "model_requested": { + "name": "model_requested", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "model_actual": { + "name": "model_actual", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "http_status": { + "name": "http_status", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "is_stream": { + "name": "is_stream", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "first_byte_latency_ms": { + "name": "first_byte_latency_ms", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "latency_ms": { + "name": "latency_ms", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "prompt_tokens": { + "name": "prompt_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "completion_tokens": { + "name": "completion_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "total_tokens": { + "name": "total_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "estimated_cost": { + "name": "estimated_cost", + "type": "real", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "billing_details": { + "name": "billing_details", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "client_family": { + "name": "client_family", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "client_app_id": { + "name": "client_app_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "client_app_name": { + "name": "client_app_name", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "client_confidence": { + "name": "client_confidence", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "retry_count": { + "name": "retry_count", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "proxy_logs_created_at_idx": { + "name": "proxy_logs_created_at_idx", + "columns": [ + "created_at" + ], + "isUnique": false + }, + "proxy_logs_account_created_at_idx": { + "name": "proxy_logs_account_created_at_idx", + "columns": [ + "account_id", + "created_at" + ], + "isUnique": false + }, + "proxy_logs_status_created_at_idx": { + "name": "proxy_logs_status_created_at_idx", + "columns": [ + "status", + "created_at" + ], + "isUnique": false + }, + "proxy_logs_model_actual_created_at_idx": { + "name": "proxy_logs_model_actual_created_at_idx", + "columns": [ + "model_actual", + "created_at" + ], + "isUnique": false + }, + "proxy_logs_downstream_api_key_created_at_idx": { + "name": "proxy_logs_downstream_api_key_created_at_idx", + "columns": [ + "downstream_api_key_id", + "created_at" + ], + "isUnique": false + }, + "proxy_logs_client_app_id_created_at_idx": { + "name": "proxy_logs_client_app_id_created_at_idx", + "columns": [ + "client_app_id", + "created_at" + ], + "isUnique": false + }, + "proxy_logs_client_family_created_at_idx": { + "name": "proxy_logs_client_family_created_at_idx", + "columns": [ + "client_family", + "created_at" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "proxy_video_tasks": { + "name": "proxy_video_tasks", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "public_id": { + "name": "public_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "upstream_video_id": { + "name": "upstream_video_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "site_url": { + "name": "site_url", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "token_value": { + "name": "token_value", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "requested_model": { + "name": "requested_model", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "actual_model": { + "name": "actual_model", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "channel_id": { + "name": "channel_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "account_id": { + "name": "account_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "status_snapshot": { + "name": "status_snapshot", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "upstream_response_meta": { + "name": "upstream_response_meta", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_upstream_status": { + "name": "last_upstream_status", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_polled_at": { + "name": "last_polled_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "proxy_video_tasks_public_id_unique": { + "name": "proxy_video_tasks_public_id_unique", + "columns": [ + "public_id" + ], + "isUnique": true + }, + "proxy_video_tasks_upstream_video_id_idx": { + "name": "proxy_video_tasks_upstream_video_id_idx", + "columns": [ + "upstream_video_id" + ], + "isUnique": false + }, + "proxy_video_tasks_created_at_idx": { + "name": "proxy_video_tasks_created_at_idx", + "columns": [ + "created_at" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "route_channels": { + "name": "route_channels", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "route_id": { + "name": "route_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "account_id": { + "name": "account_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "token_id": { + "name": "token_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "oauth_route_unit_id": { + "name": "oauth_route_unit_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "source_model": { + "name": "source_model", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "priority": { + "name": "priority", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "weight": { + "name": "weight", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 10 + }, + "enabled": { + "name": "enabled", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": true + }, + "manual_override": { + "name": "manual_override", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": false + }, + "success_count": { + "name": "success_count", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "fail_count": { + "name": "fail_count", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "total_latency_ms": { + "name": "total_latency_ms", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "total_cost": { + "name": "total_cost", + "type": "real", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "last_used_at": { + "name": "last_used_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_selected_at": { + "name": "last_selected_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_fail_at": { + "name": "last_fail_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "consecutive_fail_count": { + "name": "consecutive_fail_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "cooldown_level": { + "name": "cooldown_level", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "cooldown_until": { + "name": "cooldown_until", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "route_channels_route_id_idx": { + "name": "route_channels_route_id_idx", + "columns": [ + "route_id" + ], + "isUnique": false + }, + "route_channels_account_id_idx": { + "name": "route_channels_account_id_idx", + "columns": [ + "account_id" + ], + "isUnique": false + }, + "route_channels_token_id_idx": { + "name": "route_channels_token_id_idx", + "columns": [ + "token_id" + ], + "isUnique": false + }, + "route_channels_oauth_route_unit_id_idx": { + "name": "route_channels_oauth_route_unit_id_idx", + "columns": [ + "oauth_route_unit_id" + ], + "isUnique": false + }, + "route_channels_route_enabled_idx": { + "name": "route_channels_route_enabled_idx", + "columns": [ + "route_id", + "enabled" + ], + "isUnique": false + }, + "route_channels_route_token_idx": { + "name": "route_channels_route_token_idx", + "columns": [ + "route_id", + "token_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "route_channels_route_id_token_routes_id_fk": { + "name": "route_channels_route_id_token_routes_id_fk", + "tableFrom": "route_channels", + "tableTo": "token_routes", + "columnsFrom": [ + "route_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "route_channels_account_id_accounts_id_fk": { + "name": "route_channels_account_id_accounts_id_fk", + "tableFrom": "route_channels", + "tableTo": "accounts", + "columnsFrom": [ + "account_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "route_channels_token_id_account_tokens_id_fk": { + "name": "route_channels_token_id_account_tokens_id_fk", + "tableFrom": "route_channels", + "tableTo": "account_tokens", + "columnsFrom": [ + "token_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "route_group_sources": { + "name": "route_group_sources", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "group_route_id": { + "name": "group_route_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "source_route_id": { + "name": "source_route_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "route_group_sources_group_source_unique": { + "name": "route_group_sources_group_source_unique", + "columns": [ + "group_route_id", + "source_route_id" + ], + "isUnique": true + }, + "route_group_sources_source_route_id_idx": { + "name": "route_group_sources_source_route_id_idx", + "columns": [ + "source_route_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "route_group_sources_group_route_id_token_routes_id_fk": { + "name": "route_group_sources_group_route_id_token_routes_id_fk", + "tableFrom": "route_group_sources", + "tableTo": "token_routes", + "columnsFrom": [ + "group_route_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "route_group_sources_source_route_id_token_routes_id_fk": { + "name": "route_group_sources_source_route_id_token_routes_id_fk", + "tableFrom": "route_group_sources", + "tableTo": "token_routes", + "columnsFrom": [ + "source_route_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "settings": { + "name": "settings", + "columns": { + "key": { + "name": "key", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "site_announcements": { + "name": "site_announcements", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "site_id": { + "name": "site_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "platform": { + "name": "platform", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "source_key": { + "name": "source_key", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "level": { + "name": "level", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'info'" + }, + "source_url": { + "name": "source_url", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "starts_at": { + "name": "starts_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "ends_at": { + "name": "ends_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "upstream_created_at": { + "name": "upstream_created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "upstream_updated_at": { + "name": "upstream_updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "first_seen_at": { + "name": "first_seen_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "last_seen_at": { + "name": "last_seen_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "read_at": { + "name": "read_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "dismissed_at": { + "name": "dismissed_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "raw_payload": { + "name": "raw_payload", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "site_announcements_site_source_key_unique": { + "name": "site_announcements_site_source_key_unique", + "columns": [ + "site_id", + "source_key" + ], + "isUnique": true + }, + "site_announcements_site_id_first_seen_at_idx": { + "name": "site_announcements_site_id_first_seen_at_idx", + "columns": [ + "site_id", + "first_seen_at" + ], + "isUnique": false + }, + "site_announcements_read_at_idx": { + "name": "site_announcements_read_at_idx", + "columns": [ + "read_at" + ], + "isUnique": false + } + }, + "foreignKeys": { + "site_announcements_site_id_sites_id_fk": { + "name": "site_announcements_site_id_sites_id_fk", + "tableFrom": "site_announcements", + "tableTo": "sites", + "columnsFrom": [ + "site_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "site_api_endpoints": { + "name": "site_api_endpoints", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "site_id": { + "name": "site_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "url": { + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "enabled": { + "name": "enabled", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": true + }, + "sort_order": { + "name": "sort_order", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "cooldown_until": { + "name": "cooldown_until", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_selected_at": { + "name": "last_selected_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_failed_at": { + "name": "last_failed_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_failure_reason": { + "name": "last_failure_reason", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "site_api_endpoints_site_url_unique": { + "name": "site_api_endpoints_site_url_unique", + "columns": [ + "site_id", + "url" + ], + "isUnique": true + }, + "site_api_endpoints_site_enabled_sort_idx": { + "name": "site_api_endpoints_site_enabled_sort_idx", + "columns": [ + "site_id", + "enabled", + "sort_order" + ], + "isUnique": false + }, + "site_api_endpoints_site_cooldown_idx": { + "name": "site_api_endpoints_site_cooldown_idx", + "columns": [ + "site_id", + "cooldown_until" + ], + "isUnique": false + } + }, + "foreignKeys": { + "site_api_endpoints_site_id_sites_id_fk": { + "name": "site_api_endpoints_site_id_sites_id_fk", + "tableFrom": "site_api_endpoints", + "tableTo": "sites", + "columnsFrom": [ + "site_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "site_day_usage": { + "name": "site_day_usage", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "local_day": { + "name": "local_day", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "site_id": { + "name": "site_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "total_calls": { + "name": "total_calls", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "success_calls": { + "name": "success_calls", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "failed_calls": { + "name": "failed_calls", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "total_tokens": { + "name": "total_tokens", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "total_summary_spend": { + "name": "total_summary_spend", + "type": "real", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "total_site_spend": { + "name": "total_site_spend", + "type": "real", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "total_latency_ms": { + "name": "total_latency_ms", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "latency_count": { + "name": "latency_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "site_day_usage_day_site_unique": { + "name": "site_day_usage_day_site_unique", + "columns": [ + "local_day", + "site_id" + ], + "isUnique": true + }, + "site_day_usage_day_idx": { + "name": "site_day_usage_day_idx", + "columns": [ + "local_day" + ], + "isUnique": false + }, + "site_day_usage_site_id_idx": { + "name": "site_day_usage_site_id_idx", + "columns": [ + "site_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "site_day_usage_site_id_sites_id_fk": { + "name": "site_day_usage_site_id_sites_id_fk", + "tableFrom": "site_day_usage", + "tableTo": "sites", + "columnsFrom": [ + "site_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": { + "site_day_usage_non_negative": { + "name": "site_day_usage_non_negative", + "value": "\"site_day_usage\".\"total_calls\" >= 0 and \"site_day_usage\".\"success_calls\" >= 0 and \"site_day_usage\".\"failed_calls\" >= 0 and \"site_day_usage\".\"total_tokens\" >= 0 and \"site_day_usage\".\"total_summary_spend\" >= 0 and \"site_day_usage\".\"total_site_spend\" >= 0 and \"site_day_usage\".\"total_latency_ms\" >= 0 and \"site_day_usage\".\"latency_count\" >= 0" + } + } + }, + "site_disabled_models": { + "name": "site_disabled_models", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "site_id": { + "name": "site_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "model_name": { + "name": "model_name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "site_disabled_models_site_model_unique": { + "name": "site_disabled_models_site_model_unique", + "columns": [ + "site_id", + "model_name" + ], + "isUnique": true + }, + "site_disabled_models_site_id_idx": { + "name": "site_disabled_models_site_id_idx", + "columns": [ + "site_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "site_disabled_models_site_id_sites_id_fk": { + "name": "site_disabled_models_site_id_sites_id_fk", + "tableFrom": "site_disabled_models", + "tableTo": "sites", + "columnsFrom": [ + "site_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "site_hour_usage": { + "name": "site_hour_usage", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "bucket_start_utc": { + "name": "bucket_start_utc", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "site_id": { + "name": "site_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "total_calls": { + "name": "total_calls", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "success_calls": { + "name": "success_calls", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "failed_calls": { + "name": "failed_calls", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "total_tokens": { + "name": "total_tokens", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "total_summary_spend": { + "name": "total_summary_spend", + "type": "real", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "total_site_spend": { + "name": "total_site_spend", + "type": "real", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "total_latency_ms": { + "name": "total_latency_ms", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "latency_count": { + "name": "latency_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "site_hour_usage_hour_site_unique": { + "name": "site_hour_usage_hour_site_unique", + "columns": [ + "bucket_start_utc", + "site_id" + ], + "isUnique": true + }, + "site_hour_usage_hour_idx": { + "name": "site_hour_usage_hour_idx", + "columns": [ + "bucket_start_utc" + ], + "isUnique": false + }, + "site_hour_usage_site_id_idx": { + "name": "site_hour_usage_site_id_idx", + "columns": [ + "site_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "site_hour_usage_site_id_sites_id_fk": { + "name": "site_hour_usage_site_id_sites_id_fk", + "tableFrom": "site_hour_usage", + "tableTo": "sites", + "columnsFrom": [ + "site_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": { + "site_hour_usage_non_negative": { + "name": "site_hour_usage_non_negative", + "value": "\"site_hour_usage\".\"total_calls\" >= 0 and \"site_hour_usage\".\"success_calls\" >= 0 and \"site_hour_usage\".\"failed_calls\" >= 0 and \"site_hour_usage\".\"total_tokens\" >= 0 and \"site_hour_usage\".\"total_summary_spend\" >= 0 and \"site_hour_usage\".\"total_site_spend\" >= 0 and \"site_hour_usage\".\"total_latency_ms\" >= 0 and \"site_hour_usage\".\"latency_count\" >= 0" + } + } + }, + "sites": { + "name": "sites", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "url": { + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "external_checkin_url": { + "name": "external_checkin_url", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "platform": { + "name": "platform", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "proxy_url": { + "name": "proxy_url", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "use_system_proxy": { + "name": "use_system_proxy", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": false + }, + "custom_headers": { + "name": "custom_headers", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'active'" + }, + "is_pinned": { + "name": "is_pinned", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": false + }, + "sort_order": { + "name": "sort_order", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "global_weight": { + "name": "global_weight", + "type": "real", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 1 + }, + "api_key": { + "name": "api_key", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "sites_status_idx": { + "name": "sites_status_idx", + "columns": [ + "status" + ], + "isUnique": false + }, + "sites_platform_url_unique": { + "name": "sites_platform_url_unique", + "columns": [ + "platform", + "url" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "token_model_availability": { + "name": "token_model_availability", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "token_id": { + "name": "token_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "model_name": { + "name": "model_name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "available": { + "name": "available", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "latency_ms": { + "name": "latency_ms", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "checked_at": { + "name": "checked_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "token_model_availability_token_model_unique": { + "name": "token_model_availability_token_model_unique", + "columns": [ + "token_id", + "model_name" + ], + "isUnique": true + }, + "token_model_availability_token_available_idx": { + "name": "token_model_availability_token_available_idx", + "columns": [ + "token_id", + "available" + ], + "isUnique": false + }, + "token_model_availability_model_name_idx": { + "name": "token_model_availability_model_name_idx", + "columns": [ + "model_name" + ], + "isUnique": false + }, + "token_model_availability_available_idx": { + "name": "token_model_availability_available_idx", + "columns": [ + "available" + ], + "isUnique": false + } + }, + "foreignKeys": { + "token_model_availability_token_id_account_tokens_id_fk": { + "name": "token_model_availability_token_id_account_tokens_id_fk", + "tableFrom": "token_model_availability", + "tableTo": "account_tokens", + "columnsFrom": [ + "token_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "token_routes": { + "name": "token_routes", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "model_pattern": { + "name": "model_pattern", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "display_name": { + "name": "display_name", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "display_icon": { + "name": "display_icon", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "route_mode": { + "name": "route_mode", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'pattern'" + }, + "model_mapping": { + "name": "model_mapping", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "decision_snapshot": { + "name": "decision_snapshot", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "decision_refreshed_at": { + "name": "decision_refreshed_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "routing_strategy": { + "name": "routing_strategy", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'weighted'" + }, + "enabled": { + "name": "enabled", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "token_routes_model_pattern_idx": { + "name": "token_routes_model_pattern_idx", + "columns": [ + "model_pattern" + ], + "isUnique": false + }, + "token_routes_enabled_idx": { + "name": "token_routes_enabled_idx", + "columns": [ + "enabled" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + } + }, + "views": {}, + "enums": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + }, + "internal": { + "indexes": {} + } +} \ No newline at end of file diff --git a/drizzle/meta/_journal.json b/drizzle/meta/_journal.json index 2ade18a..66ddd28 100644 --- a/drizzle/meta/_journal.json +++ b/drizzle/meta/_journal.json @@ -148,6 +148,27 @@ "when": 1775441167045, "tag": "0021_young_shriek", "breakpoints": true + }, + { + "idx": 21, + "version": "6", + "when": 1775713163948, + "tag": "0022_admin_snapshots", + "breakpoints": true + }, + { + "idx": 22, + "version": "6", + "when": 1775721864379, + "tag": "0023_usage_aggregates", + "breakpoints": true + }, + { + "idx": 23, + "version": "6", + "when": 1775731596826, + "tag": "0024_projection_leases", + "breakpoints": true } ] } diff --git a/src/server/db/generated/mysql.bootstrap.sql b/src/server/db/generated/mysql.bootstrap.sql index 2cde346..d75f6ad 100644 --- a/src/server/db/generated/mysql.bootstrap.sql +++ b/src/server/db/generated/mysql.bootstrap.sql @@ -1,10 +1,13 @@ CREATE TABLE IF NOT EXISTS `sites` (`id` INT AUTO_INCREMENT NOT NULL PRIMARY KEY, `name` TEXT NOT NULL, `url` TEXT NOT NULL, `platform` TEXT NOT NULL, `status` VARCHAR(191) NOT NULL DEFAULT 'active', `api_key` TEXT, `created_at` VARCHAR(191) DEFAULT (DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')), `updated_at` VARCHAR(191) DEFAULT (DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')), `is_pinned` BOOLEAN DEFAULT false, `sort_order` INT DEFAULT 0, `proxy_url` TEXT, `use_system_proxy` BOOLEAN DEFAULT false, `custom_headers` JSON, `external_checkin_url` TEXT, `global_weight` DOUBLE DEFAULT 1); CREATE TABLE IF NOT EXISTS `accounts` (`id` INT AUTO_INCREMENT NOT NULL PRIMARY KEY, `site_id` INT NOT NULL, `username` TEXT, `access_token` TEXT NOT NULL, `api_token` TEXT, `balance` DOUBLE DEFAULT 0, `balance_used` DOUBLE DEFAULT 0, `quota` DOUBLE DEFAULT 0, `unit_cost` DOUBLE, `value_score` DOUBLE DEFAULT 0, `status` VARCHAR(191) DEFAULT 'active', `checkin_enabled` BOOLEAN DEFAULT true, `last_checkin_at` VARCHAR(191), `last_balance_refresh` VARCHAR(191), `extra_config` JSON, `created_at` VARCHAR(191) DEFAULT (DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')), `updated_at` VARCHAR(191) DEFAULT (DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')), `is_pinned` BOOLEAN DEFAULT false, `sort_order` INT DEFAULT 0, `oauth_provider` TEXT, `oauth_account_key` TEXT, `oauth_project_id` TEXT, FOREIGN KEY (`site_id`) REFERENCES `sites`(`id`) ON DELETE CASCADE); CREATE TABLE IF NOT EXISTS `account_tokens` (`id` INT AUTO_INCREMENT NOT NULL PRIMARY KEY, `account_id` INT NOT NULL, `name` TEXT NOT NULL, `token` TEXT NOT NULL, `source` VARCHAR(191) DEFAULT 'manual', `enabled` BOOLEAN DEFAULT true, `is_default` BOOLEAN DEFAULT false, `created_at` VARCHAR(191) DEFAULT (DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')), `updated_at` VARCHAR(191) DEFAULT (DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')), `token_group` TEXT, `value_status` VARCHAR(191) NOT NULL DEFAULT 'ready', FOREIGN KEY (`account_id`) REFERENCES `accounts`(`id`) ON DELETE CASCADE); +CREATE TABLE IF NOT EXISTS `admin_snapshots` (`id` INT AUTO_INCREMENT NOT NULL PRIMARY KEY, `namespace` TEXT NOT NULL, `snapshot_key` TEXT NOT NULL, `payload` TEXT NOT NULL, `generated_at` VARCHAR(191) NOT NULL, `expires_at` VARCHAR(191) NOT NULL, `stale_until` VARCHAR(191) NOT NULL, `created_at` VARCHAR(191) DEFAULT (DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')), `updated_at` VARCHAR(191) DEFAULT (DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s'))); +CREATE TABLE IF NOT EXISTS `analytics_projection_checkpoints` (`projector_key` VARCHAR(191) NOT NULL PRIMARY KEY, `time_zone` VARCHAR(191) NOT NULL DEFAULT 'Local', `last_proxy_log_id` INT NOT NULL DEFAULT 0, `watermark_created_at` VARCHAR(191), `recompute_from_id` INT, `recompute_requested_at` VARCHAR(191), `recompute_reason` TEXT, `recompute_started_at` VARCHAR(191), `recompute_completed_at` VARCHAR(191), `last_projected_at` VARCHAR(191), `last_successful_at` VARCHAR(191), `last_error` TEXT, `created_at` VARCHAR(191) DEFAULT (DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')), `updated_at` VARCHAR(191) DEFAULT (DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')), `lease_owner` TEXT, `lease_token` TEXT, `lease_expires_at` VARCHAR(191)); CREATE TABLE IF NOT EXISTS `checkin_logs` (`id` INT AUTO_INCREMENT NOT NULL PRIMARY KEY, `account_id` INT NOT NULL, `status` TEXT NOT NULL, `message` TEXT, `reward` TEXT, `created_at` VARCHAR(191) DEFAULT (DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')), FOREIGN KEY (`account_id`) REFERENCES `accounts`(`id`) ON DELETE CASCADE); CREATE TABLE IF NOT EXISTS `downstream_api_keys` (`id` INT AUTO_INCREMENT NOT NULL PRIMARY KEY, `name` TEXT NOT NULL, `key` TEXT NOT NULL, `description` TEXT, `enabled` BOOLEAN DEFAULT true, `expires_at` VARCHAR(191), `max_cost` DOUBLE, `used_cost` DOUBLE DEFAULT 0, `max_requests` INT, `used_requests` INT DEFAULT 0, `supported_models` JSON, `allowed_route_ids` JSON, `site_weight_multipliers` JSON, `last_used_at` VARCHAR(191), `created_at` VARCHAR(191) DEFAULT (DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')), `updated_at` VARCHAR(191) DEFAULT (DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')), `group_name` TEXT, `tags` TEXT, `excluded_site_ids` JSON, `excluded_credential_refs` JSON); CREATE TABLE IF NOT EXISTS `events` (`id` INT AUTO_INCREMENT NOT NULL PRIMARY KEY, `type` TEXT NOT NULL, `title` TEXT NOT NULL, `message` TEXT, `level` VARCHAR(191) NOT NULL DEFAULT 'info', `read` BOOLEAN DEFAULT false, `related_id` INT, `related_type` TEXT, `created_at` VARCHAR(191) DEFAULT (DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s'))); CREATE TABLE IF NOT EXISTS `model_availability` (`id` INT AUTO_INCREMENT NOT NULL PRIMARY KEY, `account_id` INT NOT NULL, `model_name` TEXT NOT NULL, `available` BOOLEAN, `latency_ms` INT, `checked_at` VARCHAR(191) DEFAULT (DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')), `is_manual` BOOLEAN DEFAULT false, FOREIGN KEY (`account_id`) REFERENCES `accounts`(`id`) ON DELETE CASCADE); +CREATE TABLE IF NOT EXISTS `model_day_usage` (`id` INT AUTO_INCREMENT NOT NULL PRIMARY KEY, `local_day` TEXT NOT NULL, `site_id` INT NOT NULL, `model` TEXT NOT NULL, `total_calls` INT NOT NULL DEFAULT 0, `success_calls` INT NOT NULL DEFAULT 0, `failed_calls` INT NOT NULL DEFAULT 0, `total_tokens` INT NOT NULL DEFAULT 0, `total_spend` DOUBLE NOT NULL DEFAULT 0, `total_latency_ms` INT NOT NULL DEFAULT 0, `latency_count` INT NOT NULL DEFAULT 0, `created_at` VARCHAR(191) DEFAULT (DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')), `updated_at` VARCHAR(191) DEFAULT (DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')), FOREIGN KEY (`site_id`) REFERENCES `sites`(`id`) ON DELETE CASCADE); CREATE TABLE IF NOT EXISTS `oauth_route_units` (`id` INT AUTO_INCREMENT NOT NULL PRIMARY KEY, `site_id` INT NOT NULL, `provider` TEXT NOT NULL, `name` TEXT NOT NULL, `strategy` VARCHAR(191) NOT NULL DEFAULT 'round_robin', `enabled` BOOLEAN DEFAULT true, `created_at` VARCHAR(191) DEFAULT (DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')), `updated_at` VARCHAR(191) DEFAULT (DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')), FOREIGN KEY (`site_id`) REFERENCES `sites`(`id`) ON DELETE CASCADE); CREATE TABLE IF NOT EXISTS `oauth_route_unit_members` (`id` INT AUTO_INCREMENT NOT NULL PRIMARY KEY, `unit_id` INT NOT NULL, `account_id` INT NOT NULL, `sort_order` INT DEFAULT 0, `success_count` INT DEFAULT 0, `fail_count` INT DEFAULT 0, `total_latency_ms` INT DEFAULT 0, `total_cost` DOUBLE DEFAULT 0, `last_used_at` VARCHAR(191), `last_selected_at` VARCHAR(191), `last_fail_at` VARCHAR(191), `consecutive_fail_count` INT NOT NULL DEFAULT 0, `cooldown_level` INT NOT NULL DEFAULT 0, `cooldown_until` VARCHAR(191), `created_at` VARCHAR(191) DEFAULT (DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')), `updated_at` VARCHAR(191) DEFAULT (DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')), FOREIGN KEY (`account_id`) REFERENCES `accounts`(`id`) ON DELETE CASCADE, FOREIGN KEY (`unit_id`) REFERENCES `oauth_route_units`(`id`) ON DELETE CASCADE); CREATE TABLE IF NOT EXISTS `proxy_debug_traces` (`id` INT AUTO_INCREMENT NOT NULL PRIMARY KEY, `downstream_path` TEXT NOT NULL, `client_kind` TEXT, `session_id` TEXT, `trace_hint` TEXT, `requested_model` TEXT, `downstream_api_key_id` INT, `request_headers_json` JSON, `request_body_json` JSON, `sticky_session_key` TEXT, `sticky_hit_channel_id` INT, `selected_channel_id` INT, `selected_route_id` INT, `selected_account_id` INT, `selected_site_id` INT, `selected_site_platform` TEXT, `endpoint_candidates_json` JSON, `endpoint_runtime_state_json` JSON, `decision_summary_json` JSON, `final_status` TEXT, `final_http_status` INT, `final_upstream_path` TEXT, `final_response_headers_json` JSON, `final_response_body_json` JSON, `created_at` VARCHAR(191) DEFAULT (DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')), `updated_at` VARCHAR(191) DEFAULT (DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s'))); @@ -18,10 +21,14 @@ CREATE TABLE IF NOT EXISTS `route_group_sources` (`id` INT AUTO_INCREMENT NOT NU CREATE TABLE IF NOT EXISTS `settings` (`key` VARCHAR(191) NOT NULL PRIMARY KEY, `value` TEXT); CREATE TABLE IF NOT EXISTS `site_announcements` (`id` INT AUTO_INCREMENT NOT NULL PRIMARY KEY, `site_id` INT NOT NULL, `platform` TEXT NOT NULL, `source_key` TEXT NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL, `level` VARCHAR(191) NOT NULL DEFAULT 'info', `source_url` TEXT, `starts_at` VARCHAR(191), `ends_at` VARCHAR(191), `upstream_created_at` VARCHAR(191), `upstream_updated_at` VARCHAR(191), `first_seen_at` VARCHAR(191) DEFAULT (DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')), `last_seen_at` VARCHAR(191) DEFAULT (DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')), `read_at` VARCHAR(191), `dismissed_at` VARCHAR(191), `raw_payload` TEXT, FOREIGN KEY (`site_id`) REFERENCES `sites`(`id`) ON DELETE CASCADE); CREATE TABLE IF NOT EXISTS `site_api_endpoints` (`id` INT AUTO_INCREMENT NOT NULL PRIMARY KEY, `site_id` INT NOT NULL, `url` TEXT NOT NULL, `enabled` BOOLEAN DEFAULT true, `sort_order` INT DEFAULT 0, `cooldown_until` VARCHAR(191), `last_selected_at` VARCHAR(191), `last_failed_at` VARCHAR(191), `last_failure_reason` TEXT, `created_at` VARCHAR(191) DEFAULT (DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')), `updated_at` VARCHAR(191) DEFAULT (DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')), FOREIGN KEY (`site_id`) REFERENCES `sites`(`id`) ON DELETE CASCADE); +CREATE TABLE IF NOT EXISTS `site_day_usage` (`id` INT AUTO_INCREMENT NOT NULL PRIMARY KEY, `local_day` TEXT NOT NULL, `site_id` INT NOT NULL, `total_calls` INT NOT NULL DEFAULT 0, `success_calls` INT NOT NULL DEFAULT 0, `failed_calls` INT NOT NULL DEFAULT 0, `total_tokens` INT NOT NULL DEFAULT 0, `total_summary_spend` DOUBLE NOT NULL DEFAULT 0, `total_site_spend` DOUBLE NOT NULL DEFAULT 0, `total_latency_ms` INT NOT NULL DEFAULT 0, `latency_count` INT NOT NULL DEFAULT 0, `created_at` VARCHAR(191) DEFAULT (DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')), `updated_at` VARCHAR(191) DEFAULT (DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')), FOREIGN KEY (`site_id`) REFERENCES `sites`(`id`) ON DELETE CASCADE); CREATE TABLE IF NOT EXISTS `site_disabled_models` (`id` INT AUTO_INCREMENT NOT NULL PRIMARY KEY, `site_id` INT NOT NULL, `model_name` TEXT NOT NULL, `created_at` VARCHAR(191) DEFAULT (DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')), FOREIGN KEY (`site_id`) REFERENCES `sites`(`id`) ON DELETE CASCADE); +CREATE TABLE IF NOT EXISTS `site_hour_usage` (`id` INT AUTO_INCREMENT NOT NULL PRIMARY KEY, `bucket_start_utc` TEXT NOT NULL, `site_id` INT NOT NULL, `total_calls` INT NOT NULL DEFAULT 0, `success_calls` INT NOT NULL DEFAULT 0, `failed_calls` INT NOT NULL DEFAULT 0, `total_tokens` INT NOT NULL DEFAULT 0, `total_summary_spend` DOUBLE NOT NULL DEFAULT 0, `total_site_spend` DOUBLE NOT NULL DEFAULT 0, `total_latency_ms` INT NOT NULL DEFAULT 0, `latency_count` INT NOT NULL DEFAULT 0, `created_at` VARCHAR(191) DEFAULT (DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')), `updated_at` VARCHAR(191) DEFAULT (DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')), FOREIGN KEY (`site_id`) REFERENCES `sites`(`id`) ON DELETE CASCADE); CREATE TABLE IF NOT EXISTS `token_model_availability` (`id` INT AUTO_INCREMENT NOT NULL PRIMARY KEY, `token_id` INT NOT NULL, `model_name` TEXT NOT NULL, `available` BOOLEAN, `latency_ms` INT, `checked_at` VARCHAR(191) DEFAULT (DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')), FOREIGN KEY (`token_id`) REFERENCES `account_tokens`(`id`) ON DELETE CASCADE); +CREATE UNIQUE INDEX `admin_snapshots_namespace_key_unique` ON `admin_snapshots` (`namespace`(191), `snapshot_key`(191)); CREATE UNIQUE INDEX `downstream_api_keys_key_unique` ON `downstream_api_keys` (`key`(191)); CREATE UNIQUE INDEX `model_availability_account_model_unique` ON `model_availability` (`account_id`, `model_name`(191)); +CREATE UNIQUE INDEX `model_day_usage_day_site_model_unique` ON `model_day_usage` (`local_day`(191), `site_id`, `model`(191)); CREATE UNIQUE INDEX `oauth_route_unit_members_account_unique` ON `oauth_route_unit_members` (`account_id`); CREATE UNIQUE INDEX `oauth_route_unit_members_unit_account_unique` ON `oauth_route_unit_members` (`unit_id`, `account_id`); CREATE UNIQUE INDEX `proxy_debug_attempts_trace_attempt_unique` ON `proxy_debug_attempts` (`trace_id`, `attempt_index`); @@ -30,7 +37,9 @@ CREATE UNIQUE INDEX `proxy_video_tasks_public_id_unique` ON `proxy_video_tasks` CREATE UNIQUE INDEX `route_group_sources_group_source_unique` ON `route_group_sources` (`group_route_id`, `source_route_id`); CREATE UNIQUE INDEX `site_announcements_site_source_key_unique` ON `site_announcements` (`site_id`, `source_key`(191)); CREATE UNIQUE INDEX `site_api_endpoints_site_url_unique` ON `site_api_endpoints` (`site_id`, `url`(191)); +CREATE UNIQUE INDEX `site_day_usage_day_site_unique` ON `site_day_usage` (`local_day`(191), `site_id`); CREATE UNIQUE INDEX `site_disabled_models_site_model_unique` ON `site_disabled_models` (`site_id`, `model_name`(191)); +CREATE UNIQUE INDEX `site_hour_usage_hour_site_unique` ON `site_hour_usage` (`bucket_start_utc`(191), `site_id`); CREATE UNIQUE INDEX `sites_platform_url_unique` ON `sites` (`platform`(191), `url`(191)); CREATE UNIQUE INDEX `token_model_availability_token_model_unique` ON `token_model_availability` (`token_id`, `model_name`(191)); CREATE INDEX `account_tokens_account_enabled_idx` ON `account_tokens` (`account_id`, `enabled`); @@ -41,6 +50,10 @@ CREATE INDEX `accounts_oauth_provider_idx` ON `accounts` (`oauth_provider`(191)) CREATE INDEX `accounts_site_id_idx` ON `accounts` (`site_id`); CREATE INDEX `accounts_site_status_idx` ON `accounts` (`site_id`, `status`(191)); CREATE INDEX `accounts_status_idx` ON `accounts` (`status`(191)); +CREATE INDEX `admin_snapshots_expires_at_idx` ON `admin_snapshots` (`expires_at`); +CREATE INDEX `admin_snapshots_stale_until_idx` ON `admin_snapshots` (`stale_until`); +CREATE INDEX `analytics_projection_checkpoints_lease_expires_at_idx` ON `analytics_projection_checkpoints` (`lease_expires_at`); +CREATE INDEX `analytics_projection_checkpoints_recompute_from_id_idx` ON `analytics_projection_checkpoints` (`recompute_from_id`); CREATE INDEX `checkin_logs_account_created_at_idx` ON `checkin_logs` (`account_id`, `created_at`); CREATE INDEX `checkin_logs_created_at_idx` ON `checkin_logs` (`created_at`); CREATE INDEX `checkin_logs_status_idx` ON `checkin_logs` (`status`(191)); @@ -52,6 +65,9 @@ CREATE INDEX `events_read_created_at_idx` ON `events` (`read`, `created_at`); CREATE INDEX `events_type_created_at_idx` ON `events` (`type`(191), `created_at`); CREATE INDEX `model_availability_account_available_idx` ON `model_availability` (`account_id`, `available`); CREATE INDEX `model_availability_model_name_idx` ON `model_availability` (`model_name`(191)); +CREATE INDEX `model_day_usage_day_idx` ON `model_day_usage` (`local_day`(191)); +CREATE INDEX `model_day_usage_model_idx` ON `model_day_usage` (`model`(191)); +CREATE INDEX `model_day_usage_site_id_idx` ON `model_day_usage` (`site_id`); CREATE INDEX `oauth_route_unit_members_unit_cooldown_idx` ON `oauth_route_unit_members` (`unit_id`, `cooldown_until`); CREATE INDEX `oauth_route_unit_members_unit_sort_idx` ON `oauth_route_unit_members` (`unit_id`, `sort_order`); CREATE INDEX `oauth_route_units_enabled_idx` ON `oauth_route_units` (`enabled`); @@ -82,7 +98,11 @@ CREATE INDEX `site_announcements_read_at_idx` ON `site_announcements` (`read_at` CREATE INDEX `site_announcements_site_id_first_seen_at_idx` ON `site_announcements` (`site_id`, `first_seen_at`); CREATE INDEX `site_api_endpoints_site_cooldown_idx` ON `site_api_endpoints` (`site_id`, `cooldown_until`); CREATE INDEX `site_api_endpoints_site_enabled_sort_idx` ON `site_api_endpoints` (`site_id`, `enabled`, `sort_order`); +CREATE INDEX `site_day_usage_day_idx` ON `site_day_usage` (`local_day`(191)); +CREATE INDEX `site_day_usage_site_id_idx` ON `site_day_usage` (`site_id`); CREATE INDEX `site_disabled_models_site_id_idx` ON `site_disabled_models` (`site_id`); +CREATE INDEX `site_hour_usage_hour_idx` ON `site_hour_usage` (`bucket_start_utc`(191)); +CREATE INDEX `site_hour_usage_site_id_idx` ON `site_hour_usage` (`site_id`); CREATE INDEX `sites_status_idx` ON `sites` (`status`(191)); CREATE INDEX `token_model_availability_available_idx` ON `token_model_availability` (`available`); CREATE INDEX `token_model_availability_model_name_idx` ON `token_model_availability` (`model_name`(191)); diff --git a/src/server/db/generated/mysql.upgrade.sql b/src/server/db/generated/mysql.upgrade.sql index 7271532..39c1018 100644 --- a/src/server/db/generated/mysql.upgrade.sql +++ b/src/server/db/generated/mysql.upgrade.sql @@ -1,10 +1 @@ -CREATE TABLE IF NOT EXISTS `oauth_route_units` (`id` INT AUTO_INCREMENT NOT NULL PRIMARY KEY, `site_id` INT NOT NULL, `provider` TEXT NOT NULL, `name` TEXT NOT NULL, `strategy` VARCHAR(191) NOT NULL DEFAULT 'round_robin', `enabled` BOOLEAN DEFAULT true, `created_at` VARCHAR(191) DEFAULT (DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')), `updated_at` VARCHAR(191) DEFAULT (DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')), FOREIGN KEY (`site_id`) REFERENCES `sites`(`id`) ON DELETE CASCADE); -CREATE TABLE IF NOT EXISTS `oauth_route_unit_members` (`id` INT AUTO_INCREMENT NOT NULL PRIMARY KEY, `unit_id` INT NOT NULL, `account_id` INT NOT NULL, `sort_order` INT DEFAULT 0, `success_count` INT DEFAULT 0, `fail_count` INT DEFAULT 0, `total_latency_ms` INT DEFAULT 0, `total_cost` DOUBLE DEFAULT 0, `last_used_at` VARCHAR(191), `last_selected_at` VARCHAR(191), `last_fail_at` VARCHAR(191), `consecutive_fail_count` INT NOT NULL DEFAULT 0, `cooldown_level` INT NOT NULL DEFAULT 0, `cooldown_until` VARCHAR(191), `created_at` VARCHAR(191) DEFAULT (DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')), `updated_at` VARCHAR(191) DEFAULT (DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')), FOREIGN KEY (`account_id`) REFERENCES `accounts`(`id`) ON DELETE CASCADE, FOREIGN KEY (`unit_id`) REFERENCES `oauth_route_units`(`id`) ON DELETE CASCADE); -ALTER TABLE `route_channels` ADD COLUMN `oauth_route_unit_id` INT; -CREATE UNIQUE INDEX `oauth_route_unit_members_account_unique` ON `oauth_route_unit_members` (`account_id`); -CREATE UNIQUE INDEX `oauth_route_unit_members_unit_account_unique` ON `oauth_route_unit_members` (`unit_id`, `account_id`); -CREATE INDEX `oauth_route_unit_members_unit_cooldown_idx` ON `oauth_route_unit_members` (`unit_id`, `cooldown_until`); -CREATE INDEX `oauth_route_unit_members_unit_sort_idx` ON `oauth_route_unit_members` (`unit_id`, `sort_order`); -CREATE INDEX `oauth_route_units_enabled_idx` ON `oauth_route_units` (`enabled`); -CREATE INDEX `oauth_route_units_site_provider_idx` ON `oauth_route_units` (`site_id`, `provider`(191)); -CREATE INDEX `route_channels_oauth_route_unit_id_idx` ON `route_channels` (`oauth_route_unit_id`); +-- no schema changes detected for mysql diff --git a/src/server/db/generated/postgres.bootstrap.sql b/src/server/db/generated/postgres.bootstrap.sql index e6375e8..a4c4e1a 100644 --- a/src/server/db/generated/postgres.bootstrap.sql +++ b/src/server/db/generated/postgres.bootstrap.sql @@ -1,10 +1,13 @@ CREATE TABLE IF NOT EXISTS "sites" ("id" INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL PRIMARY KEY, "name" TEXT NOT NULL, "url" TEXT NOT NULL, "platform" TEXT NOT NULL, "status" TEXT NOT NULL DEFAULT 'active', "api_key" TEXT, "created_at" TEXT DEFAULT to_char(timezone('UTC', CURRENT_TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS'), "updated_at" TEXT DEFAULT to_char(timezone('UTC', CURRENT_TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS'), "is_pinned" BOOLEAN DEFAULT false, "sort_order" INTEGER DEFAULT 0, "proxy_url" TEXT, "use_system_proxy" BOOLEAN DEFAULT false, "custom_headers" JSONB, "external_checkin_url" TEXT, "global_weight" DOUBLE PRECISION DEFAULT 1); CREATE TABLE IF NOT EXISTS "accounts" ("id" INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL PRIMARY KEY, "site_id" INTEGER NOT NULL, "username" TEXT, "access_token" TEXT NOT NULL, "api_token" TEXT, "balance" DOUBLE PRECISION DEFAULT 0, "balance_used" DOUBLE PRECISION DEFAULT 0, "quota" DOUBLE PRECISION DEFAULT 0, "unit_cost" DOUBLE PRECISION, "value_score" DOUBLE PRECISION DEFAULT 0, "status" TEXT DEFAULT 'active', "checkin_enabled" BOOLEAN DEFAULT true, "last_checkin_at" TEXT, "last_balance_refresh" TEXT, "extra_config" JSONB, "created_at" TEXT DEFAULT to_char(timezone('UTC', CURRENT_TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS'), "updated_at" TEXT DEFAULT to_char(timezone('UTC', CURRENT_TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS'), "is_pinned" BOOLEAN DEFAULT false, "sort_order" INTEGER DEFAULT 0, "oauth_provider" TEXT, "oauth_account_key" TEXT, "oauth_project_id" TEXT, FOREIGN KEY ("site_id") REFERENCES "sites"("id") ON DELETE CASCADE); CREATE TABLE IF NOT EXISTS "account_tokens" ("id" INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL PRIMARY KEY, "account_id" INTEGER NOT NULL, "name" TEXT NOT NULL, "token" TEXT NOT NULL, "source" TEXT DEFAULT 'manual', "enabled" BOOLEAN DEFAULT true, "is_default" BOOLEAN DEFAULT false, "created_at" TEXT DEFAULT to_char(timezone('UTC', CURRENT_TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS'), "updated_at" TEXT DEFAULT to_char(timezone('UTC', CURRENT_TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS'), "token_group" TEXT, "value_status" TEXT NOT NULL DEFAULT 'ready', FOREIGN KEY ("account_id") REFERENCES "accounts"("id") ON DELETE CASCADE); +CREATE TABLE IF NOT EXISTS "admin_snapshots" ("id" INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL PRIMARY KEY, "namespace" TEXT NOT NULL, "snapshot_key" TEXT NOT NULL, "payload" TEXT NOT NULL, "generated_at" TEXT NOT NULL, "expires_at" TEXT NOT NULL, "stale_until" TEXT NOT NULL, "created_at" TEXT DEFAULT to_char(timezone('UTC', CURRENT_TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS'), "updated_at" TEXT DEFAULT to_char(timezone('UTC', CURRENT_TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS')); +CREATE TABLE IF NOT EXISTS "analytics_projection_checkpoints" ("projector_key" TEXT NOT NULL PRIMARY KEY, "time_zone" TEXT NOT NULL DEFAULT 'Local', "last_proxy_log_id" INTEGER NOT NULL DEFAULT 0, "watermark_created_at" TEXT, "recompute_from_id" INTEGER, "recompute_requested_at" TEXT, "recompute_reason" TEXT, "recompute_started_at" TEXT, "recompute_completed_at" TEXT, "last_projected_at" TEXT, "last_successful_at" TEXT, "last_error" TEXT, "created_at" TEXT DEFAULT to_char(timezone('UTC', CURRENT_TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS'), "updated_at" TEXT DEFAULT to_char(timezone('UTC', CURRENT_TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS'), "lease_owner" TEXT, "lease_token" TEXT, "lease_expires_at" TEXT); CREATE TABLE IF NOT EXISTS "checkin_logs" ("id" INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL PRIMARY KEY, "account_id" INTEGER NOT NULL, "status" TEXT NOT NULL, "message" TEXT, "reward" TEXT, "created_at" TEXT DEFAULT to_char(timezone('UTC', CURRENT_TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS'), FOREIGN KEY ("account_id") REFERENCES "accounts"("id") ON DELETE CASCADE); CREATE TABLE IF NOT EXISTS "downstream_api_keys" ("id" INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL PRIMARY KEY, "name" TEXT NOT NULL, "key" TEXT NOT NULL, "description" TEXT, "enabled" BOOLEAN DEFAULT true, "expires_at" TEXT, "max_cost" DOUBLE PRECISION, "used_cost" DOUBLE PRECISION DEFAULT 0, "max_requests" INTEGER, "used_requests" INTEGER DEFAULT 0, "supported_models" JSONB, "allowed_route_ids" JSONB, "site_weight_multipliers" JSONB, "last_used_at" TEXT, "created_at" TEXT DEFAULT to_char(timezone('UTC', CURRENT_TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS'), "updated_at" TEXT DEFAULT to_char(timezone('UTC', CURRENT_TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS'), "group_name" TEXT, "tags" TEXT, "excluded_site_ids" JSONB, "excluded_credential_refs" JSONB); CREATE TABLE IF NOT EXISTS "events" ("id" INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL PRIMARY KEY, "type" TEXT NOT NULL, "title" TEXT NOT NULL, "message" TEXT, "level" TEXT NOT NULL DEFAULT 'info', "read" BOOLEAN DEFAULT false, "related_id" INTEGER, "related_type" TEXT, "created_at" TEXT DEFAULT to_char(timezone('UTC', CURRENT_TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS')); CREATE TABLE IF NOT EXISTS "model_availability" ("id" INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL PRIMARY KEY, "account_id" INTEGER NOT NULL, "model_name" TEXT NOT NULL, "available" BOOLEAN, "latency_ms" INTEGER, "checked_at" TEXT DEFAULT to_char(timezone('UTC', CURRENT_TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS'), "is_manual" BOOLEAN DEFAULT false, FOREIGN KEY ("account_id") REFERENCES "accounts"("id") ON DELETE CASCADE); +CREATE TABLE IF NOT EXISTS "model_day_usage" ("id" INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL PRIMARY KEY, "local_day" TEXT NOT NULL, "site_id" INTEGER NOT NULL, "model" TEXT NOT NULL, "total_calls" INTEGER NOT NULL DEFAULT 0, "success_calls" INTEGER NOT NULL DEFAULT 0, "failed_calls" INTEGER NOT NULL DEFAULT 0, "total_tokens" INTEGER NOT NULL DEFAULT 0, "total_spend" DOUBLE PRECISION NOT NULL DEFAULT 0, "total_latency_ms" INTEGER NOT NULL DEFAULT 0, "latency_count" INTEGER NOT NULL DEFAULT 0, "created_at" TEXT DEFAULT to_char(timezone('UTC', CURRENT_TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS'), "updated_at" TEXT DEFAULT to_char(timezone('UTC', CURRENT_TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS'), FOREIGN KEY ("site_id") REFERENCES "sites"("id") ON DELETE CASCADE); CREATE TABLE IF NOT EXISTS "oauth_route_units" ("id" INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL PRIMARY KEY, "site_id" INTEGER NOT NULL, "provider" TEXT NOT NULL, "name" TEXT NOT NULL, "strategy" TEXT NOT NULL DEFAULT 'round_robin', "enabled" BOOLEAN DEFAULT true, "created_at" TEXT DEFAULT to_char(timezone('UTC', CURRENT_TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS'), "updated_at" TEXT DEFAULT to_char(timezone('UTC', CURRENT_TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS'), FOREIGN KEY ("site_id") REFERENCES "sites"("id") ON DELETE CASCADE); CREATE TABLE IF NOT EXISTS "oauth_route_unit_members" ("id" INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL PRIMARY KEY, "unit_id" INTEGER NOT NULL, "account_id" INTEGER NOT NULL, "sort_order" INTEGER DEFAULT 0, "success_count" INTEGER DEFAULT 0, "fail_count" INTEGER DEFAULT 0, "total_latency_ms" INTEGER DEFAULT 0, "total_cost" DOUBLE PRECISION DEFAULT 0, "last_used_at" TEXT, "last_selected_at" TEXT, "last_fail_at" TEXT, "consecutive_fail_count" INTEGER NOT NULL DEFAULT 0, "cooldown_level" INTEGER NOT NULL DEFAULT 0, "cooldown_until" TEXT, "created_at" TEXT DEFAULT to_char(timezone('UTC', CURRENT_TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS'), "updated_at" TEXT DEFAULT to_char(timezone('UTC', CURRENT_TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS'), FOREIGN KEY ("account_id") REFERENCES "accounts"("id") ON DELETE CASCADE, FOREIGN KEY ("unit_id") REFERENCES "oauth_route_units"("id") ON DELETE CASCADE); CREATE TABLE IF NOT EXISTS "proxy_debug_traces" ("id" INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL PRIMARY KEY, "downstream_path" TEXT NOT NULL, "client_kind" TEXT, "session_id" TEXT, "trace_hint" TEXT, "requested_model" TEXT, "downstream_api_key_id" INTEGER, "request_headers_json" JSONB, "request_body_json" JSONB, "sticky_session_key" TEXT, "sticky_hit_channel_id" INTEGER, "selected_channel_id" INTEGER, "selected_route_id" INTEGER, "selected_account_id" INTEGER, "selected_site_id" INTEGER, "selected_site_platform" TEXT, "endpoint_candidates_json" JSONB, "endpoint_runtime_state_json" JSONB, "decision_summary_json" JSONB, "final_status" TEXT, "final_http_status" INTEGER, "final_upstream_path" TEXT, "final_response_headers_json" JSONB, "final_response_body_json" JSONB, "created_at" TEXT DEFAULT to_char(timezone('UTC', CURRENT_TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS'), "updated_at" TEXT DEFAULT to_char(timezone('UTC', CURRENT_TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS')); @@ -18,10 +21,14 @@ CREATE TABLE IF NOT EXISTS "route_group_sources" ("id" INTEGER GENERATED BY DEFA CREATE TABLE IF NOT EXISTS "settings" ("key" TEXT NOT NULL PRIMARY KEY, "value" TEXT); CREATE TABLE IF NOT EXISTS "site_announcements" ("id" INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL PRIMARY KEY, "site_id" INTEGER NOT NULL, "platform" TEXT NOT NULL, "source_key" TEXT NOT NULL, "title" TEXT NOT NULL, "content" TEXT NOT NULL, "level" TEXT NOT NULL DEFAULT 'info', "source_url" TEXT, "starts_at" TEXT, "ends_at" TEXT, "upstream_created_at" TEXT, "upstream_updated_at" TEXT, "first_seen_at" TEXT DEFAULT to_char(timezone('UTC', CURRENT_TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS'), "last_seen_at" TEXT DEFAULT to_char(timezone('UTC', CURRENT_TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS'), "read_at" TEXT, "dismissed_at" TEXT, "raw_payload" TEXT, FOREIGN KEY ("site_id") REFERENCES "sites"("id") ON DELETE CASCADE); CREATE TABLE IF NOT EXISTS "site_api_endpoints" ("id" INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL PRIMARY KEY, "site_id" INTEGER NOT NULL, "url" TEXT NOT NULL, "enabled" BOOLEAN DEFAULT true, "sort_order" INTEGER DEFAULT 0, "cooldown_until" TEXT, "last_selected_at" TEXT, "last_failed_at" TEXT, "last_failure_reason" TEXT, "created_at" TEXT DEFAULT to_char(timezone('UTC', CURRENT_TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS'), "updated_at" TEXT DEFAULT to_char(timezone('UTC', CURRENT_TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS'), FOREIGN KEY ("site_id") REFERENCES "sites"("id") ON DELETE CASCADE); +CREATE TABLE IF NOT EXISTS "site_day_usage" ("id" INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL PRIMARY KEY, "local_day" TEXT NOT NULL, "site_id" INTEGER NOT NULL, "total_calls" INTEGER NOT NULL DEFAULT 0, "success_calls" INTEGER NOT NULL DEFAULT 0, "failed_calls" INTEGER NOT NULL DEFAULT 0, "total_tokens" INTEGER NOT NULL DEFAULT 0, "total_summary_spend" DOUBLE PRECISION NOT NULL DEFAULT 0, "total_site_spend" DOUBLE PRECISION NOT NULL DEFAULT 0, "total_latency_ms" INTEGER NOT NULL DEFAULT 0, "latency_count" INTEGER NOT NULL DEFAULT 0, "created_at" TEXT DEFAULT to_char(timezone('UTC', CURRENT_TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS'), "updated_at" TEXT DEFAULT to_char(timezone('UTC', CURRENT_TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS'), FOREIGN KEY ("site_id") REFERENCES "sites"("id") ON DELETE CASCADE); CREATE TABLE IF NOT EXISTS "site_disabled_models" ("id" INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL PRIMARY KEY, "site_id" INTEGER NOT NULL, "model_name" TEXT NOT NULL, "created_at" TEXT DEFAULT to_char(timezone('UTC', CURRENT_TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS'), FOREIGN KEY ("site_id") REFERENCES "sites"("id") ON DELETE CASCADE); +CREATE TABLE IF NOT EXISTS "site_hour_usage" ("id" INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL PRIMARY KEY, "bucket_start_utc" TEXT NOT NULL, "site_id" INTEGER NOT NULL, "total_calls" INTEGER NOT NULL DEFAULT 0, "success_calls" INTEGER NOT NULL DEFAULT 0, "failed_calls" INTEGER NOT NULL DEFAULT 0, "total_tokens" INTEGER NOT NULL DEFAULT 0, "total_summary_spend" DOUBLE PRECISION NOT NULL DEFAULT 0, "total_site_spend" DOUBLE PRECISION NOT NULL DEFAULT 0, "total_latency_ms" INTEGER NOT NULL DEFAULT 0, "latency_count" INTEGER NOT NULL DEFAULT 0, "created_at" TEXT DEFAULT to_char(timezone('UTC', CURRENT_TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS'), "updated_at" TEXT DEFAULT to_char(timezone('UTC', CURRENT_TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS'), FOREIGN KEY ("site_id") REFERENCES "sites"("id") ON DELETE CASCADE); CREATE TABLE IF NOT EXISTS "token_model_availability" ("id" INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL PRIMARY KEY, "token_id" INTEGER NOT NULL, "model_name" TEXT NOT NULL, "available" BOOLEAN, "latency_ms" INTEGER, "checked_at" TEXT DEFAULT to_char(timezone('UTC', CURRENT_TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS'), FOREIGN KEY ("token_id") REFERENCES "account_tokens"("id") ON DELETE CASCADE); +CREATE UNIQUE INDEX "admin_snapshots_namespace_key_unique" ON "admin_snapshots" ("namespace", "snapshot_key"); CREATE UNIQUE INDEX "downstream_api_keys_key_unique" ON "downstream_api_keys" ("key"); CREATE UNIQUE INDEX "model_availability_account_model_unique" ON "model_availability" ("account_id", "model_name"); +CREATE UNIQUE INDEX "model_day_usage_day_site_model_unique" ON "model_day_usage" ("local_day", "site_id", "model"); CREATE UNIQUE INDEX "oauth_route_unit_members_account_unique" ON "oauth_route_unit_members" ("account_id"); CREATE UNIQUE INDEX "oauth_route_unit_members_unit_account_unique" ON "oauth_route_unit_members" ("unit_id", "account_id"); CREATE UNIQUE INDEX "proxy_debug_attempts_trace_attempt_unique" ON "proxy_debug_attempts" ("trace_id", "attempt_index"); @@ -30,7 +37,9 @@ CREATE UNIQUE INDEX "proxy_video_tasks_public_id_unique" ON "proxy_video_tasks" CREATE UNIQUE INDEX "route_group_sources_group_source_unique" ON "route_group_sources" ("group_route_id", "source_route_id"); CREATE UNIQUE INDEX "site_announcements_site_source_key_unique" ON "site_announcements" ("site_id", "source_key"); CREATE UNIQUE INDEX "site_api_endpoints_site_url_unique" ON "site_api_endpoints" ("site_id", "url"); +CREATE UNIQUE INDEX "site_day_usage_day_site_unique" ON "site_day_usage" ("local_day", "site_id"); CREATE UNIQUE INDEX "site_disabled_models_site_model_unique" ON "site_disabled_models" ("site_id", "model_name"); +CREATE UNIQUE INDEX "site_hour_usage_hour_site_unique" ON "site_hour_usage" ("bucket_start_utc", "site_id"); CREATE UNIQUE INDEX "sites_platform_url_unique" ON "sites" ("platform", "url"); CREATE UNIQUE INDEX "token_model_availability_token_model_unique" ON "token_model_availability" ("token_id", "model_name"); CREATE INDEX "account_tokens_account_enabled_idx" ON "account_tokens" ("account_id", "enabled"); @@ -41,6 +50,10 @@ CREATE INDEX "accounts_oauth_provider_idx" ON "accounts" ("oauth_provider"); CREATE INDEX "accounts_site_id_idx" ON "accounts" ("site_id"); CREATE INDEX "accounts_site_status_idx" ON "accounts" ("site_id", "status"); CREATE INDEX "accounts_status_idx" ON "accounts" ("status"); +CREATE INDEX "admin_snapshots_expires_at_idx" ON "admin_snapshots" ("expires_at"); +CREATE INDEX "admin_snapshots_stale_until_idx" ON "admin_snapshots" ("stale_until"); +CREATE INDEX "analytics_projection_checkpoints_lease_expires_at_idx" ON "analytics_projection_checkpoints" ("lease_expires_at"); +CREATE INDEX "analytics_projection_checkpoints_recompute_from_id_idx" ON "analytics_projection_checkpoints" ("recompute_from_id"); CREATE INDEX "checkin_logs_account_created_at_idx" ON "checkin_logs" ("account_id", "created_at"); CREATE INDEX "checkin_logs_created_at_idx" ON "checkin_logs" ("created_at"); CREATE INDEX "checkin_logs_status_idx" ON "checkin_logs" ("status"); @@ -52,6 +65,9 @@ CREATE INDEX "events_read_created_at_idx" ON "events" ("read", "created_at"); CREATE INDEX "events_type_created_at_idx" ON "events" ("type", "created_at"); CREATE INDEX "model_availability_account_available_idx" ON "model_availability" ("account_id", "available"); CREATE INDEX "model_availability_model_name_idx" ON "model_availability" ("model_name"); +CREATE INDEX "model_day_usage_day_idx" ON "model_day_usage" ("local_day"); +CREATE INDEX "model_day_usage_model_idx" ON "model_day_usage" ("model"); +CREATE INDEX "model_day_usage_site_id_idx" ON "model_day_usage" ("site_id"); CREATE INDEX "oauth_route_unit_members_unit_cooldown_idx" ON "oauth_route_unit_members" ("unit_id", "cooldown_until"); CREATE INDEX "oauth_route_unit_members_unit_sort_idx" ON "oauth_route_unit_members" ("unit_id", "sort_order"); CREATE INDEX "oauth_route_units_enabled_idx" ON "oauth_route_units" ("enabled"); @@ -82,7 +98,11 @@ CREATE INDEX "site_announcements_read_at_idx" ON "site_announcements" ("read_at" CREATE INDEX "site_announcements_site_id_first_seen_at_idx" ON "site_announcements" ("site_id", "first_seen_at"); CREATE INDEX "site_api_endpoints_site_cooldown_idx" ON "site_api_endpoints" ("site_id", "cooldown_until"); CREATE INDEX "site_api_endpoints_site_enabled_sort_idx" ON "site_api_endpoints" ("site_id", "enabled", "sort_order"); +CREATE INDEX "site_day_usage_day_idx" ON "site_day_usage" ("local_day"); +CREATE INDEX "site_day_usage_site_id_idx" ON "site_day_usage" ("site_id"); CREATE INDEX "site_disabled_models_site_id_idx" ON "site_disabled_models" ("site_id"); +CREATE INDEX "site_hour_usage_hour_idx" ON "site_hour_usage" ("bucket_start_utc"); +CREATE INDEX "site_hour_usage_site_id_idx" ON "site_hour_usage" ("site_id"); CREATE INDEX "sites_status_idx" ON "sites" ("status"); CREATE INDEX "token_model_availability_available_idx" ON "token_model_availability" ("available"); CREATE INDEX "token_model_availability_model_name_idx" ON "token_model_availability" ("model_name"); diff --git a/src/server/db/generated/postgres.upgrade.sql b/src/server/db/generated/postgres.upgrade.sql index ab72704..bf33dfa 100644 --- a/src/server/db/generated/postgres.upgrade.sql +++ b/src/server/db/generated/postgres.upgrade.sql @@ -1,10 +1 @@ -CREATE TABLE IF NOT EXISTS "oauth_route_units" ("id" INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL PRIMARY KEY, "site_id" INTEGER NOT NULL, "provider" TEXT NOT NULL, "name" TEXT NOT NULL, "strategy" TEXT NOT NULL DEFAULT 'round_robin', "enabled" BOOLEAN DEFAULT true, "created_at" TEXT DEFAULT to_char(timezone('UTC', CURRENT_TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS'), "updated_at" TEXT DEFAULT to_char(timezone('UTC', CURRENT_TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS'), FOREIGN KEY ("site_id") REFERENCES "sites"("id") ON DELETE CASCADE); -CREATE TABLE IF NOT EXISTS "oauth_route_unit_members" ("id" INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL PRIMARY KEY, "unit_id" INTEGER NOT NULL, "account_id" INTEGER NOT NULL, "sort_order" INTEGER DEFAULT 0, "success_count" INTEGER DEFAULT 0, "fail_count" INTEGER DEFAULT 0, "total_latency_ms" INTEGER DEFAULT 0, "total_cost" DOUBLE PRECISION DEFAULT 0, "last_used_at" TEXT, "last_selected_at" TEXT, "last_fail_at" TEXT, "consecutive_fail_count" INTEGER NOT NULL DEFAULT 0, "cooldown_level" INTEGER NOT NULL DEFAULT 0, "cooldown_until" TEXT, "created_at" TEXT DEFAULT to_char(timezone('UTC', CURRENT_TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS'), "updated_at" TEXT DEFAULT to_char(timezone('UTC', CURRENT_TIMESTAMP), 'YYYY-MM-DD HH24:MI:SS'), FOREIGN KEY ("account_id") REFERENCES "accounts"("id") ON DELETE CASCADE, FOREIGN KEY ("unit_id") REFERENCES "oauth_route_units"("id") ON DELETE CASCADE); -ALTER TABLE "route_channels" ADD COLUMN "oauth_route_unit_id" INTEGER; -CREATE UNIQUE INDEX "oauth_route_unit_members_account_unique" ON "oauth_route_unit_members" ("account_id"); -CREATE UNIQUE INDEX "oauth_route_unit_members_unit_account_unique" ON "oauth_route_unit_members" ("unit_id", "account_id"); -CREATE INDEX "oauth_route_unit_members_unit_cooldown_idx" ON "oauth_route_unit_members" ("unit_id", "cooldown_until"); -CREATE INDEX "oauth_route_unit_members_unit_sort_idx" ON "oauth_route_unit_members" ("unit_id", "sort_order"); -CREATE INDEX "oauth_route_units_enabled_idx" ON "oauth_route_units" ("enabled"); -CREATE INDEX "oauth_route_units_site_provider_idx" ON "oauth_route_units" ("site_id", "provider"); -CREATE INDEX "route_channels_oauth_route_unit_id_idx" ON "route_channels" ("oauth_route_unit_id"); +-- no schema changes detected for postgres diff --git a/src/server/db/generated/schemaContract.json b/src/server/db/generated/schemaContract.json index da951d5..774e81d 100644 --- a/src/server/db/generated/schemaContract.json +++ b/src/server/db/generated/schemaContract.json @@ -206,6 +206,170 @@ } } }, + "admin_snapshots": { + "columns": { + "id": { + "logicalType": "integer", + "notNull": true, + "defaultValue": null, + "primaryKey": true + }, + "namespace": { + "logicalType": "text", + "notNull": true, + "defaultValue": null, + "primaryKey": false + }, + "snapshot_key": { + "logicalType": "text", + "notNull": true, + "defaultValue": null, + "primaryKey": false + }, + "payload": { + "logicalType": "text", + "notNull": true, + "defaultValue": null, + "primaryKey": false + }, + "generated_at": { + "logicalType": "datetime", + "notNull": true, + "defaultValue": null, + "primaryKey": false + }, + "expires_at": { + "logicalType": "datetime", + "notNull": true, + "defaultValue": null, + "primaryKey": false + }, + "stale_until": { + "logicalType": "datetime", + "notNull": true, + "defaultValue": null, + "primaryKey": false + }, + "created_at": { + "logicalType": "datetime", + "notNull": false, + "defaultValue": "datetime('now')", + "primaryKey": false + }, + "updated_at": { + "logicalType": "datetime", + "notNull": false, + "defaultValue": "datetime('now')", + "primaryKey": false + } + } + }, + "analytics_projection_checkpoints": { + "columns": { + "projector_key": { + "logicalType": "text", + "notNull": true, + "defaultValue": null, + "primaryKey": true + }, + "time_zone": { + "logicalType": "text", + "notNull": true, + "defaultValue": "'Local'", + "primaryKey": false + }, + "last_proxy_log_id": { + "logicalType": "integer", + "notNull": true, + "defaultValue": "0", + "primaryKey": false + }, + "watermark_created_at": { + "logicalType": "datetime", + "notNull": false, + "defaultValue": null, + "primaryKey": false + }, + "recompute_from_id": { + "logicalType": "integer", + "notNull": false, + "defaultValue": null, + "primaryKey": false + }, + "recompute_requested_at": { + "logicalType": "datetime", + "notNull": false, + "defaultValue": null, + "primaryKey": false + }, + "recompute_reason": { + "logicalType": "text", + "notNull": false, + "defaultValue": null, + "primaryKey": false + }, + "recompute_started_at": { + "logicalType": "datetime", + "notNull": false, + "defaultValue": null, + "primaryKey": false + }, + "recompute_completed_at": { + "logicalType": "datetime", + "notNull": false, + "defaultValue": null, + "primaryKey": false + }, + "last_projected_at": { + "logicalType": "datetime", + "notNull": false, + "defaultValue": null, + "primaryKey": false + }, + "last_successful_at": { + "logicalType": "datetime", + "notNull": false, + "defaultValue": null, + "primaryKey": false + }, + "last_error": { + "logicalType": "text", + "notNull": false, + "defaultValue": null, + "primaryKey": false + }, + "created_at": { + "logicalType": "datetime", + "notNull": false, + "defaultValue": "datetime('now')", + "primaryKey": false + }, + "updated_at": { + "logicalType": "datetime", + "notNull": false, + "defaultValue": "datetime('now')", + "primaryKey": false + }, + "lease_owner": { + "logicalType": "text", + "notNull": false, + "defaultValue": null, + "primaryKey": false + }, + "lease_token": { + "logicalType": "text", + "notNull": false, + "defaultValue": null, + "primaryKey": false + }, + "lease_expires_at": { + "logicalType": "datetime", + "notNull": false, + "defaultValue": null, + "primaryKey": false + } + } + }, "checkin_logs": { "columns": { "id": { @@ -474,6 +638,88 @@ } } }, + "model_day_usage": { + "columns": { + "id": { + "logicalType": "integer", + "notNull": true, + "defaultValue": null, + "primaryKey": true + }, + "local_day": { + "logicalType": "text", + "notNull": true, + "defaultValue": null, + "primaryKey": false + }, + "site_id": { + "logicalType": "integer", + "notNull": true, + "defaultValue": null, + "primaryKey": false + }, + "model": { + "logicalType": "text", + "notNull": true, + "defaultValue": null, + "primaryKey": false + }, + "total_calls": { + "logicalType": "integer", + "notNull": true, + "defaultValue": "0", + "primaryKey": false + }, + "success_calls": { + "logicalType": "integer", + "notNull": true, + "defaultValue": "0", + "primaryKey": false + }, + "failed_calls": { + "logicalType": "integer", + "notNull": true, + "defaultValue": "0", + "primaryKey": false + }, + "total_tokens": { + "logicalType": "integer", + "notNull": true, + "defaultValue": "0", + "primaryKey": false + }, + "total_spend": { + "logicalType": "real", + "notNull": true, + "defaultValue": "0", + "primaryKey": false + }, + "total_latency_ms": { + "logicalType": "integer", + "notNull": true, + "defaultValue": "0", + "primaryKey": false + }, + "latency_count": { + "logicalType": "integer", + "notNull": true, + "defaultValue": "0", + "primaryKey": false + }, + "created_at": { + "logicalType": "datetime", + "notNull": false, + "defaultValue": "datetime('now')", + "primaryKey": false + }, + "updated_at": { + "logicalType": "datetime", + "notNull": false, + "defaultValue": "datetime('now')", + "primaryKey": false + } + } + }, "oauth_route_unit_members": { "columns": { "id": { @@ -1560,6 +1806,88 @@ } } }, + "site_day_usage": { + "columns": { + "id": { + "logicalType": "integer", + "notNull": true, + "defaultValue": null, + "primaryKey": true + }, + "local_day": { + "logicalType": "text", + "notNull": true, + "defaultValue": null, + "primaryKey": false + }, + "site_id": { + "logicalType": "integer", + "notNull": true, + "defaultValue": null, + "primaryKey": false + }, + "total_calls": { + "logicalType": "integer", + "notNull": true, + "defaultValue": "0", + "primaryKey": false + }, + "success_calls": { + "logicalType": "integer", + "notNull": true, + "defaultValue": "0", + "primaryKey": false + }, + "failed_calls": { + "logicalType": "integer", + "notNull": true, + "defaultValue": "0", + "primaryKey": false + }, + "total_tokens": { + "logicalType": "integer", + "notNull": true, + "defaultValue": "0", + "primaryKey": false + }, + "total_summary_spend": { + "logicalType": "real", + "notNull": true, + "defaultValue": "0", + "primaryKey": false + }, + "total_site_spend": { + "logicalType": "real", + "notNull": true, + "defaultValue": "0", + "primaryKey": false + }, + "total_latency_ms": { + "logicalType": "integer", + "notNull": true, + "defaultValue": "0", + "primaryKey": false + }, + "latency_count": { + "logicalType": "integer", + "notNull": true, + "defaultValue": "0", + "primaryKey": false + }, + "created_at": { + "logicalType": "datetime", + "notNull": false, + "defaultValue": "datetime('now')", + "primaryKey": false + }, + "updated_at": { + "logicalType": "datetime", + "notNull": false, + "defaultValue": "datetime('now')", + "primaryKey": false + } + } + }, "site_disabled_models": { "columns": { "id": { @@ -1588,6 +1916,88 @@ } } }, + "site_hour_usage": { + "columns": { + "id": { + "logicalType": "integer", + "notNull": true, + "defaultValue": null, + "primaryKey": true + }, + "bucket_start_utc": { + "logicalType": "text", + "notNull": true, + "defaultValue": null, + "primaryKey": false + }, + "site_id": { + "logicalType": "integer", + "notNull": true, + "defaultValue": null, + "primaryKey": false + }, + "total_calls": { + "logicalType": "integer", + "notNull": true, + "defaultValue": "0", + "primaryKey": false + }, + "success_calls": { + "logicalType": "integer", + "notNull": true, + "defaultValue": "0", + "primaryKey": false + }, + "failed_calls": { + "logicalType": "integer", + "notNull": true, + "defaultValue": "0", + "primaryKey": false + }, + "total_tokens": { + "logicalType": "integer", + "notNull": true, + "defaultValue": "0", + "primaryKey": false + }, + "total_summary_spend": { + "logicalType": "real", + "notNull": true, + "defaultValue": "0", + "primaryKey": false + }, + "total_site_spend": { + "logicalType": "real", + "notNull": true, + "defaultValue": "0", + "primaryKey": false + }, + "total_latency_ms": { + "logicalType": "integer", + "notNull": true, + "defaultValue": "0", + "primaryKey": false + }, + "latency_count": { + "logicalType": "integer", + "notNull": true, + "defaultValue": "0", + "primaryKey": false + }, + "created_at": { + "logicalType": "datetime", + "notNull": false, + "defaultValue": "datetime('now')", + "primaryKey": false + }, + "updated_at": { + "logicalType": "datetime", + "notNull": false, + "defaultValue": "datetime('now')", + "primaryKey": false + } + } + }, "sites": { "columns": { "id": { @@ -1868,6 +2278,47 @@ ], "unique": false }, + { + "name": "admin_snapshots_expires_at_idx", + "table": "admin_snapshots", + "columns": [ + "expires_at" + ], + "unique": false + }, + { + "name": "admin_snapshots_namespace_key_unique", + "table": "admin_snapshots", + "columns": [ + "namespace", + "snapshot_key" + ], + "unique": true + }, + { + "name": "admin_snapshots_stale_until_idx", + "table": "admin_snapshots", + "columns": [ + "stale_until" + ], + "unique": false + }, + { + "name": "analytics_projection_checkpoints_lease_expires_at_idx", + "table": "analytics_projection_checkpoints", + "columns": [ + "lease_expires_at" + ], + "unique": false + }, + { + "name": "analytics_projection_checkpoints_recompute_from_id_idx", + "table": "analytics_projection_checkpoints", + "columns": [ + "recompute_from_id" + ], + "unique": false + }, { "name": "checkin_logs_account_created_at_idx", "table": "checkin_logs", @@ -1977,6 +2428,40 @@ ], "unique": false }, + { + "name": "model_day_usage_day_idx", + "table": "model_day_usage", + "columns": [ + "local_day" + ], + "unique": false + }, + { + "name": "model_day_usage_day_site_model_unique", + "table": "model_day_usage", + "columns": [ + "local_day", + "site_id", + "model" + ], + "unique": true + }, + { + "name": "model_day_usage_model_idx", + "table": "model_day_usage", + "columns": [ + "model" + ], + "unique": false + }, + { + "name": "model_day_usage_site_id_idx", + "table": "model_day_usage", + "columns": [ + "site_id" + ], + "unique": false + }, { "name": "oauth_route_unit_members_account_unique", "table": "oauth_route_unit_members", @@ -2307,6 +2792,31 @@ ], "unique": true }, + { + "name": "site_day_usage_day_idx", + "table": "site_day_usage", + "columns": [ + "local_day" + ], + "unique": false + }, + { + "name": "site_day_usage_day_site_unique", + "table": "site_day_usage", + "columns": [ + "local_day", + "site_id" + ], + "unique": true + }, + { + "name": "site_day_usage_site_id_idx", + "table": "site_day_usage", + "columns": [ + "site_id" + ], + "unique": false + }, { "name": "site_disabled_models_site_id_idx", "table": "site_disabled_models", @@ -2324,6 +2834,31 @@ ], "unique": true }, + { + "name": "site_hour_usage_hour_idx", + "table": "site_hour_usage", + "columns": [ + "bucket_start_utc" + ], + "unique": false + }, + { + "name": "site_hour_usage_hour_site_unique", + "table": "site_hour_usage", + "columns": [ + "bucket_start_utc", + "site_id" + ], + "unique": true + }, + { + "name": "site_hour_usage_site_id_idx", + "table": "site_hour_usage", + "columns": [ + "site_id" + ], + "unique": false + }, { "name": "sites_platform_url_unique", "table": "sites", @@ -2393,6 +2928,14 @@ } ], "uniques": [ + { + "name": "admin_snapshots_namespace_key_unique", + "table": "admin_snapshots", + "columns": [ + "namespace", + "snapshot_key" + ] + }, { "name": "downstream_api_keys_key_unique", "table": "downstream_api_keys", @@ -2408,6 +2951,15 @@ "model_name" ] }, + { + "name": "model_day_usage_day_site_model_unique", + "table": "model_day_usage", + "columns": [ + "local_day", + "site_id", + "model" + ] + }, { "name": "oauth_route_unit_members_account_unique", "table": "oauth_route_unit_members", @@ -2469,6 +3021,14 @@ "url" ] }, + { + "name": "site_day_usage_day_site_unique", + "table": "site_day_usage", + "columns": [ + "local_day", + "site_id" + ] + }, { "name": "site_disabled_models_site_model_unique", "table": "site_disabled_models", @@ -2477,6 +3037,14 @@ "model_name" ] }, + { + "name": "site_hour_usage_hour_site_unique", + "table": "site_hour_usage", + "columns": [ + "bucket_start_utc", + "site_id" + ] + }, { "name": "sites_platform_url_unique", "table": "sites", @@ -2539,6 +3107,17 @@ ], "onDelete": "CASCADE" }, + { + "table": "model_day_usage", + "columns": [ + "site_id" + ], + "referencedTable": "sites", + "referencedColumns": [ + "id" + ], + "onDelete": "CASCADE" + }, { "table": "oauth_route_unit_members", "columns": [ @@ -2660,6 +3239,17 @@ ], "onDelete": "CASCADE" }, + { + "table": "site_day_usage", + "columns": [ + "site_id" + ], + "referencedTable": "sites", + "referencedColumns": [ + "id" + ], + "onDelete": "CASCADE" + }, { "table": "site_disabled_models", "columns": [ @@ -2671,6 +3261,17 @@ ], "onDelete": "CASCADE" }, + { + "table": "site_hour_usage", + "columns": [ + "site_id" + ], + "referencedTable": "sites", + "referencedColumns": [ + "id" + ], + "onDelete": "CASCADE" + }, { "table": "token_model_availability", "columns": [ diff --git a/src/server/db/schema.ts b/src/server/db/schema.ts index ea95f75..99cc007 100644 --- a/src/server/db/schema.ts +++ b/src/server/db/schema.ts @@ -1,4 +1,4 @@ -import { sqliteTable, text, integer, real, uniqueIndex, index } from 'drizzle-orm/sqlite-core'; +import { sqliteTable, text, integer, real, uniqueIndex, index, check } from 'drizzle-orm/sqlite-core'; import { sql } from 'drizzle-orm'; export const sites = sqliteTable('sites', { @@ -374,6 +374,118 @@ export const settings = sqliteTable('settings', { value: text('value'), // JSON }); +export const adminSnapshots = sqliteTable('admin_snapshots', { + id: integer('id').primaryKey({ autoIncrement: true }), + namespace: text('namespace').notNull(), + snapshotKey: text('snapshot_key').notNull(), + payload: text('payload').notNull(), + generatedAt: text('generated_at').notNull(), + expiresAt: text('expires_at').notNull(), + staleUntil: text('stale_until').notNull(), + createdAt: text('created_at').default(sql`(datetime('now'))`), + updatedAt: text('updated_at').default(sql`(datetime('now'))`), +}, (table) => ({ + namespaceKeyUnique: uniqueIndex('admin_snapshots_namespace_key_unique').on(table.namespace, table.snapshotKey), + expiresAtIdx: index('admin_snapshots_expires_at_idx').on(table.expiresAt), + staleUntilIdx: index('admin_snapshots_stale_until_idx').on(table.staleUntil), +})); + +export const analyticsProjectionCheckpoints = sqliteTable('analytics_projection_checkpoints', { + projectorKey: text('projector_key').primaryKey(), + timeZone: text('time_zone').notNull().default('Local'), + lastProxyLogId: integer('last_proxy_log_id').notNull().default(0), + watermarkCreatedAt: text('watermark_created_at'), + leaseOwner: text('lease_owner'), + leaseToken: text('lease_token'), + leaseExpiresAt: text('lease_expires_at'), + recomputeFromId: integer('recompute_from_id'), + recomputeRequestedAt: text('recompute_requested_at'), + recomputeReason: text('recompute_reason'), + recomputeStartedAt: text('recompute_started_at'), + recomputeCompletedAt: text('recompute_completed_at'), + lastProjectedAt: text('last_projected_at'), + lastSuccessfulAt: text('last_successful_at'), + lastError: text('last_error'), + createdAt: text('created_at').default(sql`(datetime('now'))`), + updatedAt: text('updated_at').default(sql`(datetime('now'))`), +}, (table) => ({ + recomputeFromIdIdx: index('analytics_projection_checkpoints_recompute_from_id_idx').on(table.recomputeFromId), + leaseExpiresAtIdx: index('analytics_projection_checkpoints_lease_expires_at_idx').on(table.leaseExpiresAt), +})); + +export const siteDayUsage = sqliteTable('site_day_usage', { + id: integer('id').primaryKey({ autoIncrement: true }), + localDay: text('local_day').notNull(), + siteId: integer('site_id').notNull().references(() => sites.id, { onDelete: 'cascade' }), + totalCalls: integer('total_calls').notNull().default(0), + successCalls: integer('success_calls').notNull().default(0), + failedCalls: integer('failed_calls').notNull().default(0), + totalTokens: integer('total_tokens').notNull().default(0), + totalSummarySpend: real('total_summary_spend').notNull().default(0), + totalSiteSpend: real('total_site_spend').notNull().default(0), + totalLatencyMs: integer('total_latency_ms').notNull().default(0), + latencyCount: integer('latency_count').notNull().default(0), + createdAt: text('created_at').default(sql`(datetime('now'))`), + updatedAt: text('updated_at').default(sql`(datetime('now'))`), +}, (table) => ({ + daySiteUnique: uniqueIndex('site_day_usage_day_site_unique').on(table.localDay, table.siteId), + dayIdx: index('site_day_usage_day_idx').on(table.localDay), + siteIdx: index('site_day_usage_site_id_idx').on(table.siteId), + nonNegative: check( + 'site_day_usage_non_negative', + sql`${table.totalCalls} >= 0 and ${table.successCalls} >= 0 and ${table.failedCalls} >= 0 and ${table.totalTokens} >= 0 and ${table.totalSummarySpend} >= 0 and ${table.totalSiteSpend} >= 0 and ${table.totalLatencyMs} >= 0 and ${table.latencyCount} >= 0`, + ), +})); + +export const siteHourUsage = sqliteTable('site_hour_usage', { + id: integer('id').primaryKey({ autoIncrement: true }), + bucketStartUtc: text('bucket_start_utc').notNull(), + siteId: integer('site_id').notNull().references(() => sites.id, { onDelete: 'cascade' }), + totalCalls: integer('total_calls').notNull().default(0), + successCalls: integer('success_calls').notNull().default(0), + failedCalls: integer('failed_calls').notNull().default(0), + totalTokens: integer('total_tokens').notNull().default(0), + totalSummarySpend: real('total_summary_spend').notNull().default(0), + totalSiteSpend: real('total_site_spend').notNull().default(0), + totalLatencyMs: integer('total_latency_ms').notNull().default(0), + latencyCount: integer('latency_count').notNull().default(0), + createdAt: text('created_at').default(sql`(datetime('now'))`), + updatedAt: text('updated_at').default(sql`(datetime('now'))`), +}, (table) => ({ + hourSiteUnique: uniqueIndex('site_hour_usage_hour_site_unique').on(table.bucketStartUtc, table.siteId), + hourIdx: index('site_hour_usage_hour_idx').on(table.bucketStartUtc), + siteIdx: index('site_hour_usage_site_id_idx').on(table.siteId), + nonNegative: check( + 'site_hour_usage_non_negative', + sql`${table.totalCalls} >= 0 and ${table.successCalls} >= 0 and ${table.failedCalls} >= 0 and ${table.totalTokens} >= 0 and ${table.totalSummarySpend} >= 0 and ${table.totalSiteSpend} >= 0 and ${table.totalLatencyMs} >= 0 and ${table.latencyCount} >= 0`, + ), +})); + +export const modelDayUsage = sqliteTable('model_day_usage', { + id: integer('id').primaryKey({ autoIncrement: true }), + localDay: text('local_day').notNull(), + siteId: integer('site_id').notNull().references(() => sites.id, { onDelete: 'cascade' }), + model: text('model').notNull(), + totalCalls: integer('total_calls').notNull().default(0), + successCalls: integer('success_calls').notNull().default(0), + failedCalls: integer('failed_calls').notNull().default(0), + totalTokens: integer('total_tokens').notNull().default(0), + totalSpend: real('total_spend').notNull().default(0), + totalLatencyMs: integer('total_latency_ms').notNull().default(0), + latencyCount: integer('latency_count').notNull().default(0), + createdAt: text('created_at').default(sql`(datetime('now'))`), + updatedAt: text('updated_at').default(sql`(datetime('now'))`), +}, (table) => ({ + daySiteModelUnique: uniqueIndex('model_day_usage_day_site_model_unique').on(table.localDay, table.siteId, table.model), + dayIdx: index('model_day_usage_day_idx').on(table.localDay), + siteIdx: index('model_day_usage_site_id_idx').on(table.siteId), + modelIdx: index('model_day_usage_model_idx').on(table.model), + nonNegative: check( + 'model_day_usage_non_negative', + sql`${table.totalCalls} >= 0 and ${table.successCalls} >= 0 and ${table.failedCalls} >= 0 and ${table.totalTokens} >= 0 and ${table.totalSpend} >= 0 and ${table.totalLatencyMs} >= 0 and ${table.latencyCount} >= 0`, + ), +})); + export const downstreamApiKeys = sqliteTable('downstream_api_keys', { id: integer('id').primaryKey({ autoIncrement: true }), name: text('name').notNull(), diff --git a/src/server/db/schemaArtifactGenerator.test.ts b/src/server/db/schemaArtifactGenerator.test.ts index 7a38f45..8194387 100644 --- a/src/server/db/schemaArtifactGenerator.test.ts +++ b/src/server/db/schemaArtifactGenerator.test.ts @@ -29,6 +29,8 @@ describe('schema artifact generator', () => { expect(artifacts.mysqlBootstrap).toContain('CREATE TABLE IF NOT EXISTS `sites`'); expect(artifacts.mysqlBootstrap).toContain('CREATE TABLE IF NOT EXISTS `site_disabled_models`'); expect(artifacts.postgresBootstrap).toContain('CREATE TABLE IF NOT EXISTS "account_tokens"'); + expect(artifacts.mysqlBootstrap).toContain('`snapshot_key` TEXT NOT NULL'); + expect(artifacts.postgresBootstrap).toContain('"snapshot_key" TEXT NOT NULL'); expect(artifacts.postgresBootstrap).toContain('"token_group"'); }); diff --git a/src/server/db/schemaContract.test.ts b/src/server/db/schemaContract.test.ts index b3961fc..db9c019 100644 --- a/src/server/db/schemaContract.test.ts +++ b/src/server/db/schemaContract.test.ts @@ -19,6 +19,11 @@ describe('schema contract generation', () => { expect(contract.tables.site_disabled_models).toBeDefined(); expect(contract.tables.downstream_api_keys).toBeDefined(); expect(contract.tables.proxy_files).toBeDefined(); + expect(contract.tables.admin_snapshots.columns.snapshot_key).toMatchObject({ + logicalType: 'text', + notNull: true, + primaryKey: false, + }); expect(contract.tables.proxy_video_tasks).toBeDefined(); expect(contract.tables.route_channels.columns.source_model).toBeDefined(); expect(contract.tables.route_channels.columns.last_selected_at).toBeDefined(); diff --git a/src/server/db/schemaMetadata.ts b/src/server/db/schemaMetadata.ts index 203e901..c892f4c 100644 --- a/src/server/db/schemaMetadata.ts +++ b/src/server/db/schemaMetadata.ts @@ -39,7 +39,7 @@ function isDateTimeLikeColumn(columnName: string, defaultValue: string | null): function isJsonLikeColumn(columnName: string): boolean { const normalizedColumn = columnName.toLowerCase(); return normalizedColumn.endsWith('_json') - || normalizedColumn.includes('snapshot') + || normalizedColumn.endsWith('_snapshot') || normalizedColumn.includes('mapping') || normalizedColumn.includes('headers') || normalizedColumn.includes('config') diff --git a/src/server/index.ts b/src/server/index.ts index e1a7fa1..f42dfe4 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -49,6 +49,14 @@ import { stopSub2ApiManagedRefreshScheduler, } from './services/sub2apiRefreshScheduler.js'; import { startUpdateCenterPolling, stopUpdateCenterPolling } from './services/updateCenterPollingService.js'; +import { + startAdminSnapshotWarmScheduler, + stopAdminSnapshotWarmScheduler, +} from './services/adminSnapshotWarmService.js'; +import { + startUsageAggregationProjectorScheduler, + stopUsageAggregationProjectorScheduler, +} from './services/usageAggregationService.js'; import { reloadBackupWebdavScheduler } from './services/backupService.js'; import { ensureRuntimeDatabaseReady } from './runtimeDatabaseBootstrap.js'; import { isPublicApiRoute, registerDesktopRoutes } from './desktop.js'; @@ -260,6 +268,8 @@ startModelAvailabilityProbeScheduler(); startChannelRecoveryProbeScheduler(); startSub2ApiManagedRefreshScheduler(); startUpdateCenterPolling(); +startUsageAggregationProjectorScheduler(); +startAdminSnapshotWarmScheduler(); try { await startOAuthLoopbackCallbackServers(); } catch (error) { @@ -274,6 +284,8 @@ app.addHook('onClose', async () => { stopProxyLogRetentionService(); stopModelAvailabilityProbeScheduler(); stopChannelRecoveryProbeScheduler(); + await stopUsageAggregationProjectorScheduler(); + await stopAdminSnapshotWarmScheduler(); await stopSub2ApiManagedRefreshScheduler(); await stopOAuthLoopbackCallbackServers(); }); diff --git a/src/server/proxy-core/surfaces/sharedSurface.usage-source.test.ts b/src/server/proxy-core/surfaces/sharedSurface.usage-source.test.ts index 2fecaba..842210d 100644 --- a/src/server/proxy-core/surfaces/sharedSurface.usage-source.test.ts +++ b/src/server/proxy-core/surfaces/sharedSurface.usage-source.test.ts @@ -58,6 +58,7 @@ vi.mock('../orchestration/upstreamRequest.js', () => ({ })); vi.mock('../../services/oauth/quota.js', () => ({ + recordOauthQuotaHeadersSnapshot: vi.fn(), recordOauthQuotaResetHint: vi.fn(), })); diff --git a/src/server/routes/api/accountTokens.sync.test.ts b/src/server/routes/api/accountTokens.sync.test.ts index 5c951d3..fe0d5cb 100644 --- a/src/server/routes/api/accountTokens.sync.test.ts +++ b/src/server/routes/api/accountTokens.sync.test.ts @@ -2,7 +2,7 @@ import Fastify, { type FastifyInstance } from 'fastify'; import { describe, expect, it, beforeAll, beforeEach, afterAll, vi } from 'vitest'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; -import { mkdtempSync } from 'node:fs'; +import { mkdtempSync, rmSync } from 'node:fs'; import { and, eq, sql } from 'drizzle-orm'; import { mergeAccountExtraConfig } from '../../services/accountExtraConfig.js'; @@ -32,6 +32,7 @@ describe('account tokens sync routes with site status', () => { let schema: DbModule['schema']; let maskToken: AccountTokenServiceModule['maskToken']; let dataDir = ''; + let previousDataDir: string | undefined; let seedId = 0; const nextSeed = () => { @@ -61,7 +62,9 @@ describe('account tokens sync routes with site status', () => { }; beforeAll(async () => { + previousDataDir = process.env.DATA_DIR; dataDir = mkdtempSync(join(tmpdir(), 'metapi-account-tokens-sync-')); + vi.resetModules(); process.env.DATA_DIR = dataDir; await import('../../db/migrate.js'); @@ -96,7 +99,12 @@ describe('account tokens sync routes with site status', () => { afterAll(async () => { await app.close(); - delete process.env.DATA_DIR; + if (previousDataDir === undefined) { + delete process.env.DATA_DIR; + } else { + process.env.DATA_DIR = previousDataDir; + } + rmSync(dataDir, { recursive: true, force: true }); }); it('returns skipped for single-account sync when site is disabled', async () => { diff --git a/src/server/routes/api/accounts.credentialMode.test.ts b/src/server/routes/api/accounts.credentialMode.test.ts index bd64dd0..0b9dcde 100644 --- a/src/server/routes/api/accounts.credentialMode.test.ts +++ b/src/server/routes/api/accounts.credentialMode.test.ts @@ -207,11 +207,16 @@ describe('accounts credential mode', { timeout: 15_000 }, () => { }); expect(listResponse.statusCode).toBe(200); - const list = listResponse.json() as Array<{ - id: number; - runtimeHealth?: { state?: string; reason?: string }; - capabilities?: { proxyOnly?: boolean }; - }>; + const body = listResponse.json() as { + generatedAt: string; + accounts: Array<{ + id: number; + runtimeHealth?: { state?: string; reason?: string }; + capabilities?: { proxyOnly?: boolean }; + }>; + sites: any[]; + }; + const list = body.accounts; expect(list).toHaveLength(1); expect(list[0]?.capabilities?.proxyOnly).toBe(true); expect(list[0]?.runtimeHealth).toMatchObject({ @@ -258,23 +263,28 @@ describe('accounts credential mode', { timeout: 15_000 }, () => { }); expect(listResponse.statusCode).toBe(200); - const list = listResponse.json() as Array<{ - id: number; - credentialMode?: string; - capabilities?: { - canCheckin?: boolean; - canRefreshBalance?: boolean; - proxyOnly?: boolean; - }; - }>; + const body = listResponse.json() as { + generatedAt: string; + accounts: Array<{ + id: number; + credentialMode?: string; + capabilities?: { + canCheckin?: boolean; + canRefreshBalance?: boolean; + proxyOnly?: boolean; + }; + }>; + sites: any[]; + }; + const list = body.accounts; const item = list.find((entry) => entry.id === account.id); expect(item?.credentialMode).toBe('session'); - expect(item?.capabilities).toMatchObject({ - canCheckin: false, - canRefreshBalance: false, - proxyOnly: true, - }); + expect(item?.capabilities).toMatchObject({ + canCheckin: false, + canRefreshBalance: false, + proxyOnly: true, }); + }); it('uses structured oauth columns when listing oauth account capabilities and runtime health', async () => { const site = await db.insert(schema.sites).values({ @@ -314,18 +324,23 @@ describe('accounts credential mode', { timeout: 15_000 }, () => { }); expect(listResponse.statusCode).toBe(200); - const list = listResponse.json() as Array<{ - id: number; - capabilities?: { - canCheckin?: boolean; - canRefreshBalance?: boolean; - proxyOnly?: boolean; - }; - runtimeHealth?: { - state?: string; - reason?: string; - }; - }>; + const body = listResponse.json() as { + generatedAt: string; + accounts: Array<{ + id: number; + capabilities?: { + canCheckin?: boolean; + canRefreshBalance?: boolean; + proxyOnly?: boolean; + }; + runtimeHealth?: { + state?: string; + reason?: string; + }; + }>; + sites: any[]; + }; + const list = body.accounts; const item = list.find((entry) => entry.id === account.id); expect(item?.capabilities).toMatchObject({ canCheckin: false, diff --git a/src/server/routes/api/accounts.snapshot-v2.test.ts b/src/server/routes/api/accounts.snapshot-v2.test.ts new file mode 100644 index 0000000..b0d3213 --- /dev/null +++ b/src/server/routes/api/accounts.snapshot-v2.test.ts @@ -0,0 +1,142 @@ +import Fastify, { type FastifyInstance } from "fastify"; +import { afterAll, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { mkdtempSync, rmSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { + formatLocalDate, + formatUtcSqlDateTime, +} from "../../services/localTimeService.js"; + +type DbModule = typeof import("../../db/index.js"); + +describe("accounts snapshot v2", () => { + let app: FastifyInstance; + let db: DbModule["db"]; + let schema: DbModule["schema"]; + let dataDir = ""; + let previousDataDir: string | undefined; + + beforeAll(async () => { + previousDataDir = process.env.DATA_DIR; + dataDir = mkdtempSync(join(tmpdir(), "metapi-accounts-snapshot-v2-")); + process.env.DATA_DIR = dataDir; + + await import("../../db/migrate.js"); + const dbModule = await import("../../db/index.js"); + const routesModule = await import("./accounts.js"); + db = dbModule.db; + schema = dbModule.schema; + + app = Fastify(); + await app.register(routesModule.accountsRoutes); + }); + + beforeEach(async () => { + await db.delete(schema.adminSnapshots).run(); + await db.delete(schema.proxyLogs).run(); + await db.delete(schema.checkinLogs).run(); + await db.delete(schema.routeChannels).run(); + await db.delete(schema.tokenRoutes).run(); + await db.delete(schema.tokenModelAvailability).run(); + await db.delete(schema.modelAvailability).run(); + await db.delete(schema.accountTokens).run(); + await db.delete(schema.accounts).run(); + await db.delete(schema.sites).run(); + }); + + afterAll(async () => { + await app.close(); + if (previousDataDir === undefined) { + delete process.env.DATA_DIR; + } else { + process.env.DATA_DIR = previousDataDir; + } + rmSync(dataDir, { recursive: true, force: true }); + }); + + it("returns accounts and sites in one snapshot payload", async () => { + const today = formatLocalDate(new Date()); + const site = await db + .insert(schema.sites) + .values({ + name: "snapshot-site", + url: "https://snapshot-site.example.com", + platform: "new-api", + }) + .returning() + .get(); + + const account = await db + .insert(schema.accounts) + .values({ + siteId: site.id, + username: "snapshot-user", + accessToken: "snapshot-token", + status: "active", + balance: 18.5, + extraConfig: JSON.stringify({ + todayIncomeSnapshot: { + day: today, + baseline: 3.2, + latest: 3.2, + updatedAt: `${today}T08:00:00.000Z`, + }, + }), + }) + .returning() + .get(); + + await db + .insert(schema.proxyLogs) + .values({ + accountId: account.id, + status: "success", + estimatedCost: 1.25, + createdAt: formatUtcSqlDateTime(new Date()), + }) + .run(); + + await db + .insert(schema.checkinLogs) + .values({ + accountId: account.id, + status: "success", + reward: "", + message: "checkin success", + createdAt: `${today} 09:00:00`, + }) + .run(); + + const response = await app.inject({ + method: "GET", + url: "/api/accounts", + }); + + expect(response.statusCode).toBe(200); + expect(response.headers["x-accounts-snapshot-cache"]).toBeTruthy(); + const body = response.json() as { + generatedAt: string; + accounts: Array<{ + id: number; + site: { id: number; name: string }; + todaySpend: number; + todayReward: number; + }>; + sites: Array<{ id: number; name: string }>; + }; + + expect(Date.parse(body.generatedAt)).not.toBeNaN(); + expect(body.sites).toEqual([ + expect.objectContaining({ id: site.id, name: "snapshot-site" }), + ]); + expect(body.accounts).toEqual([ + expect.objectContaining({ + id: account.id, + site: expect.objectContaining({ id: site.id, name: "snapshot-site" }), + todaySpend: 1.25, + todayReward: 3.2, + }), + ]); + }); +}); diff --git a/src/server/routes/api/accounts.todayRewardFallback.test.ts b/src/server/routes/api/accounts.todayRewardFallback.test.ts index 4411703..72bb392 100644 --- a/src/server/routes/api/accounts.todayRewardFallback.test.ts +++ b/src/server/routes/api/accounts.todayRewardFallback.test.ts @@ -89,7 +89,12 @@ describe('accounts api today reward fallback', () => { }); expect(response.statusCode).toBe(200); - const rows = response.json() as Array<{ id: number; todayReward: number }>; + const body = response.json() as { + generatedAt: string; + accounts: Array<{ id: number; todayReward: number }>; + sites: any[]; + }; + const rows = body.accounts; const target = rows.find((row) => row.id === account.id); expect(target?.todayReward).toBe(12.5); }); @@ -122,7 +127,12 @@ describe('accounts api today reward fallback', () => { }); expect(response.statusCode).toBe(200); - const rows = response.json() as Array<{ id: number; todayReward: number }>; + const body = response.json() as { + generatedAt: string; + accounts: Array<{ id: number; todayReward: number }>; + sites: any[]; + }; + const rows = body.accounts; const target = rows.find((row) => row.id === account.id); expect(target?.todayReward).toBe(1.8); }); @@ -163,7 +173,12 @@ describe('accounts api today reward fallback', () => { }); expect(response.statusCode).toBe(200); - const rows = response.json() as Array<{ id: number; todayReward: number }>; + const body = response.json() as { + generatedAt: string; + accounts: Array<{ id: number; todayReward: number }>; + sites: any[]; + }; + const rows = body.accounts; const target = rows.find((row) => row.id === account.id); expect(target?.todayReward).toBe(1.2); }); @@ -215,7 +230,12 @@ describe('accounts api today reward fallback', () => { }); expect(response.statusCode).toBe(200); - const rows = response.json() as Array<{ id: number; todaySpend: number }>; + const body = response.json() as { + generatedAt: string; + accounts: Array<{ id: number; todaySpend: number }>; + sites: any[]; + }; + const rows = body.accounts; const target = rows.find((row) => row.id === account.id); expect(target?.todaySpend).toBe(2); }); @@ -251,7 +271,12 @@ describe('accounts api today reward fallback', () => { }); expect(response.statusCode).toBe(200); - const rows = response.json() as Array<{ id: number; todaySpend: number }>; + const body = response.json() as { + generatedAt: string; + accounts: Array<{ id: number; todaySpend: number }>; + sites: any[]; + }; + const rows = body.accounts; const target = rows.find((row) => row.id === account.id); expect(target?.todaySpend).toBe(2.25); }); diff --git a/src/server/routes/api/accounts.ts b/src/server/routes/api/accounts.ts index eeda591..0d36b3c 100644 --- a/src/server/routes/api/accounts.ts +++ b/src/server/routes/api/accounts.ts @@ -1,13 +1,13 @@ -import { FastifyInstance } from 'fastify'; -import { db, schema, runtimeDbDialect } from '../../db/index.js'; -import { insertAndGetById } from '../../db/insertHelpers.js'; -import { and, eq, gte, lt, sql } from 'drizzle-orm'; -import { refreshBalance } from '../../services/balanceService.js'; -import { getAdapter } from '../../services/platforms/index.js'; +import { FastifyInstance } from "fastify"; +import { db, schema, runtimeDbDialect } from "../../db/index.js"; +import { insertAndGetById } from "../../db/insertHelpers.js"; +import { and, eq, gte, lt, sql } from "drizzle-orm"; +import { refreshBalance } from "../../services/balanceService.js"; +import { getAdapter } from "../../services/platforms/index.js"; import { convergeAccountMutation, rebuildRoutesBestEffort, -} from '../../services/accountMutationWorkflow.js'; +} from "../../services/accountMutationWorkflow.js"; import { getCredentialModeFromExtraConfig, getProxyUrlFromExtraConfig, @@ -18,21 +18,26 @@ import { normalizeCredentialMode as normalizeCredentialModeInput, resolvePlatformUserId, type AccountCredentialMode, -} from '../../services/accountExtraConfig.js'; -import { encryptAccountPassword } from '../../services/accountCredentialService.js'; -import { applyAccountUpdateWorkflow } from '../../services/accountUpdateWorkflow.js'; -import { startBackgroundTask } from '../../services/backgroundTaskService.js'; -import { parseCheckinRewardAmount } from '../../services/checkinRewardParser.js'; -import { estimateRewardWithTodayIncomeFallback } from '../../services/todayIncomeRewardService.js'; -import { getLocalDayRangeUtc } from '../../services/localTimeService.js'; +} from "../../services/accountExtraConfig.js"; +import { encryptAccountPassword } from "../../services/accountCredentialService.js"; +import { applyAccountUpdateWorkflow } from "../../services/accountUpdateWorkflow.js"; +import { startBackgroundTask } from "../../services/backgroundTaskService.js"; +import { parseCheckinRewardAmount } from "../../services/checkinRewardParser.js"; +import { estimateRewardWithTodayIncomeFallback } from "../../services/todayIncomeRewardService.js"; +import { getLocalDayRangeUtc } from "../../services/localTimeService.js"; import { buildRuntimeHealthForAccount, setAccountRuntimeHealth, type RuntimeHealthState, -} from '../../services/accountHealthService.js'; -import { appendSessionTokenRebindHint } from '../../services/alertRules.js'; -import { parseSiteProxyUrlInput, withAccountProxyOverride, withSiteRecordProxyRequestInit } from '../../services/siteProxy.js'; -import { createRateLimitGuard } from '../../middleware/requestRateLimit.js'; +} from "../../services/accountHealthService.js"; +import { appendSessionTokenRebindHint } from "../../services/alertRules.js"; +import { + parseSiteProxyUrlInput, + withAccountProxyOverride, + withSiteRecordProxyRequestInit, +} from "../../services/siteProxy.js"; +import { createRateLimitGuard } from "../../middleware/requestRateLimit.js"; +import { getAccountsSnapshot } from "../../services/accountsOverviewService.js"; import { type AccountCreatePayload, parseAccountBatchPayload, @@ -43,10 +48,16 @@ import { parseAccountRebindSessionPayload, parseAccountUpdatePayload, parseAccountVerifyTokenPayload, -} from '../../contracts/accountsRoutePayloads.js'; -import { requireSiteApiBaseUrl, runWithSiteApiEndpointPool } from '../../services/siteApiEndpointService.js'; -import { buildBatchApiKeyConnectionName, parseBatchApiKeys } from '../../services/apiKeyBatch.js'; -import { createManualAccount } from '../../services/manualAccountCreationService.js'; +} from "../../contracts/accountsRoutePayloads.js"; +import { + requireSiteApiBaseUrl, + runWithSiteApiEndpointPool, +} from "../../services/siteApiEndpointService.js"; +import { + buildBatchApiKeyConnectionName, + parseBatchApiKeys, +} from "../../services/apiKeyBatch.js"; +import { createManualAccount } from "../../services/manualAccountCreationService.js"; type AccountWithSiteRow = { accounts: typeof schema.accounts.$inferSelect; @@ -57,7 +68,7 @@ type AccountHealthRefreshResult = { accountId: number; username: string | null; siteName: string; - status: 'success' | 'failed' | 'skipped'; + status: "success" | "failed" | "skipped"; state: RuntimeHealthState; message: string; }; @@ -68,38 +79,56 @@ type AccountCapabilities = { proxyOnly: boolean; }; -type VerifyFailureReason = 'needs-user-id' | 'invalid-user-id' | 'shield-blocked' | null; +type VerifyFailureReason = + | "needs-user-id" + | "invalid-user-id" + | "shield-blocked" + | null; const limitAccountLogin = createRateLimitGuard({ - bucket: 'accounts-login', + bucket: "accounts-login", max: 5, windowMs: 60_000, }); const limitAccountVerifyToken = createRateLimitGuard({ - bucket: 'accounts-verify-token', + bucket: "accounts-verify-token", max: 5, windowMs: 60_000, }); +function parseBooleanFlag(raw?: string): boolean { + if (!raw) return false; + const normalized = raw.trim().toLowerCase(); + return normalized === "1" || normalized === "true" || normalized === "yes"; +} + function hasSessionTokenValue(value: string | null | undefined): boolean { - return typeof value === 'string' && value.trim().length > 0; + return typeof value === "string" && value.trim().length > 0; } function resolveRequestedCredentialMode(input: unknown): AccountCredentialMode { - return normalizeCredentialModeInput(input) || 'auto'; + return normalizeCredentialModeInput(input) || "auto"; } -function resolveStoredCredentialMode(account: typeof schema.accounts.$inferSelect): AccountCredentialMode { +function resolveStoredCredentialMode( + account: typeof schema.accounts.$inferSelect, +): AccountCredentialMode { const fromConfig = getCredentialModeFromExtraConfig(account.extraConfig); - if (fromConfig && fromConfig !== 'auto') return fromConfig; - return hasSessionTokenValue(account.accessToken) ? 'session' : 'apikey'; + if (fromConfig && fromConfig !== "auto") return fromConfig; + return hasSessionTokenValue(account.accessToken) ? "session" : "apikey"; } function buildCapabilitiesFromCredentialMode( credentialMode: AccountCredentialMode, hasSessionToken: boolean, - oauthIdentity?: string | null | Pick, + oauthIdentity?: + | string + | null + | Pick< + typeof schema.accounts.$inferSelect, + "extraConfig" | "oauthProvider" + >, ): AccountCapabilities { if (hasOauthProvider(oauthIdentity)) { return { @@ -108,9 +137,12 @@ function buildCapabilitiesFromCredentialMode( proxyOnly: true, }; } - const sessionCapable = credentialMode === 'session' - ? hasSessionToken - : (credentialMode === 'apikey' ? false : hasSessionToken); + const sessionCapable = + credentialMode === "session" + ? hasSessionToken + : credentialMode === "apikey" + ? false + : hasSessionToken; return { canCheckin: sessionCapable, canRefreshBalance: sessionCapable, @@ -118,9 +150,15 @@ function buildCapabilitiesFromCredentialMode( }; } -function buildCapabilitiesForAccount(account: typeof schema.accounts.$inferSelect): AccountCapabilities { +function buildCapabilitiesForAccount( + account: typeof schema.accounts.$inferSelect, +): AccountCapabilities { const credentialMode = resolveStoredCredentialMode(account); - return buildCapabilitiesFromCredentialMode(credentialMode, hasSessionTokenValue(account.accessToken), account); + return buildCapabilitiesFromCredentialMode( + credentialMode, + hasSessionTokenValue(account.accessToken), + account, + ); } function normalizeBatchIds(input: unknown): number[] { @@ -132,12 +170,12 @@ function normalizeBatchIds(input: unknown): number[] { function normalizePinnedFlag(input: unknown): boolean | null { if (input === undefined || input === null) return null; - if (typeof input === 'boolean') return input; - if (typeof input === 'number') return input !== 0; - if (typeof input === 'string') { + if (typeof input === "boolean") return input; + if (typeof input === "number") return input !== 0; + if (typeof input === "string") { const normalized = input.trim().toLowerCase(); - if (normalized === 'true' || normalized === '1') return true; - if (normalized === 'false' || normalized === '0') return false; + if (normalized === "true" || normalized === "1") return true; + if (normalized === "false" || normalized === "0") return false; } return null; } @@ -146,8 +184,8 @@ function resolveRequestedCreateTokens( body: AccountCreatePayload, credentialMode: AccountCredentialMode, ): string[] { - if (credentialMode !== 'apikey') { - const single = String(body.accessToken || '').trim(); + if (credentialMode !== "apikey") { + const single = String(body.accessToken || "").trim(); return single ? [single] : []; } @@ -157,21 +195,22 @@ function resolveRequestedCreateTokens( } function normalizeSortOrder(input: unknown): number | null { - if (input === undefined || input === null || input === '') return null; + if (input === undefined || input === null || input === "") return null; const parsed = Number.parseInt(String(input), 10); if (!Number.isFinite(parsed)) return null; return Math.max(0, parsed); } function normalizeManagedRefreshToken(input: unknown): string | undefined { - if (typeof input !== 'string') return undefined; + if (typeof input !== "string") return undefined; const trimmed = input.trim(); return trimmed.length > 0 ? trimmed : undefined; } function normalizeManagedTokenExpiresAt(input: unknown): number | undefined { - if (typeof input === 'number' && Number.isFinite(input) && input > 0) return Math.trunc(input); - if (typeof input === 'string') { + if (typeof input === "number" && Number.isFinite(input) && input > 0) + return Math.trunc(input); + if (typeof input === "string") { const parsed = Number.parseInt(input.trim(), 10); if (Number.isFinite(parsed) && parsed > 0) return parsed; } @@ -179,8 +218,14 @@ function normalizeManagedTokenExpiresAt(input: unknown): number | undefined { } async function getNextAccountSortOrder(): Promise { - const rows = await db.select({ sortOrder: schema.accounts.sortOrder }).from(schema.accounts).all(); - const max = rows.reduce((currentMax, row) => Math.max(currentMax, row.sortOrder || 0), -1); + const rows = await db + .select({ sortOrder: schema.accounts.sortOrder }) + .from(schema.accounts) + .all(); + const max = rows.reduce( + (currentMax, row) => Math.max(currentMax, row.sortOrder || 0), + -1, + ); return max + 1; } @@ -193,50 +238,55 @@ const ACCOUNT_HEALTH_REFRESH_TIMEOUT_MS = 10_000; const ACCOUNT_VERIFY_TIMEOUT_MS = 10_000; const ACCOUNT_VERIFY_DIAG_TIMEOUT_MS = 2_500; -function normalizeLoginFailure(message: string | null | undefined): LoginFailureInfo { - const raw = (message || '').trim(); +function normalizeLoginFailure( + message: string | null | undefined, +): LoginFailureInfo { + const raw = (message || "").trim(); const lowered = raw.toLowerCase(); - const looksLikeHtmlJsonParseError = ( - lowered.includes('unexpected token') - && lowered.includes('not valid json') - && (lowered.includes(' item.state === 'healthy').length, - unhealthy: results.filter((item) => item.state === 'unhealthy').length, - degraded: results.filter((item) => item.state === 'degraded').length, - disabled: results.filter((item) => item.state === 'disabled').length, - unknown: results.filter((item) => item.state === 'unknown').length, - success: results.filter((item) => item.status === 'success').length, - failed: results.filter((item) => item.status === 'failed').length, - skipped: results.filter((item) => item.status === 'skipped').length, + healthy: results.filter((item) => item.state === "healthy").length, + unhealthy: results.filter((item) => item.state === "unhealthy").length, + degraded: results.filter((item) => item.state === "degraded").length, + disabled: results.filter((item) => item.state === "disabled").length, + unknown: results.filter((item) => item.state === "unknown").length, + success: results.filter((item) => item.status === "success").length, + failed: results.filter((item) => item.status === "failed").length, + skipped: results.filter((item) => item.status === "skipped").length, }; } -async function withTimeout(fn: () => Promise, timeoutMs: number, timeoutMessage: string): Promise { +async function withTimeout( + fn: () => Promise, + timeoutMs: number, + timeoutMessage: string, +): Promise { let timer: ReturnType | null = null; try { return await Promise.race([ @@ -251,14 +301,20 @@ async function withTimeout(fn: () => Promise, timeoutMs: number, timeoutMe } function isVerificationTimeoutError(error: unknown): boolean { - const name = typeof error === 'object' && error && 'name' in error - ? String((error as { name?: unknown }).name || '') - : ''; - const message = typeof error === 'object' && error && 'message' in error - ? String((error as { message?: unknown }).message || '') - : String(error || ''); + const name = + typeof error === "object" && error && "name" in error + ? String((error as { name?: unknown }).name || "") + : ""; + const message = + typeof error === "object" && error && "message" in error + ? String((error as { message?: unknown }).message || "") + : String(error || ""); const lowered = `${name} ${message}`.toLowerCase(); - return lowered.includes('timeout') || lowered.includes('timed out') || lowered.includes('abort'); + return ( + lowered.includes("timeout") || + lowered.includes("timed out") || + lowered.includes("abort") + ); } function buildAccountVerifyTimeoutMessage(): string { @@ -286,54 +342,64 @@ async function getModelsWithSiteApiEndpointPool( }); } -function resolveUserIdFailureReason(message: string, hasProvidedUserId: boolean): VerifyFailureReason { - const lowered = String(message || '').trim().toLowerCase(); +function resolveUserIdFailureReason( + message: string, + hasProvidedUserId: boolean, +): VerifyFailureReason { + const lowered = String(message || "") + .trim() + .toLowerCase(); if (!lowered) return null; if ( - lowered.includes('mismatch') - || lowered.includes('not match') - || lowered.includes('invalid user id') - || lowered.includes('wrong user id') + lowered.includes("mismatch") || + lowered.includes("not match") || + lowered.includes("invalid user id") || + lowered.includes("wrong user id") ) { - return 'invalid-user-id'; + return "invalid-user-id"; } if ( - lowered.includes('missing new-api-user') - || lowered.includes('new-api-user required') - || lowered.includes('requires user id') - || lowered.includes('missing user id') + lowered.includes("missing new-api-user") || + lowered.includes("new-api-user required") || + lowered.includes("requires user id") || + lowered.includes("missing user id") ) { - return 'needs-user-id'; + return "needs-user-id"; } - if (lowered.includes('new-api-user') || lowered.includes('user id')) { - return hasProvidedUserId ? 'invalid-user-id' : 'needs-user-id'; + if (lowered.includes("new-api-user") || lowered.includes("user id")) { + return hasProvidedUserId ? "invalid-user-id" : "needs-user-id"; } return null; } -async function refreshRuntimeHealthForRow(row: AccountWithSiteRow): Promise { +async function refreshRuntimeHealthForRow( + row: AccountWithSiteRow, +): Promise { const accountId = row.accounts.id; const username = row.accounts.username; const siteName = row.sites.name; const capabilities = buildCapabilitiesForAccount(row.accounts); - if ((row.accounts.status || 'active') === 'disabled' || (row.sites.status || 'active') === 'disabled') { + if ( + (row.accounts.status || "active") === "disabled" || + (row.sites.status || "active") === "disabled" + ) { setAccountRuntimeHealth(accountId, { - state: 'disabled', - reason: '账号或站点已禁用', - source: 'health-refresh', + state: "disabled", + reason: "账号或站点已禁用", + source: "health-refresh", }); return { accountId, username, siteName, - status: 'skipped', - state: 'disabled', - message: '账号或站点已禁用', + status: "skipped", + state: "disabled", + message: "账号或站点已禁用", }; } @@ -342,9 +408,9 @@ async function refreshRuntimeHealthForRow(row: AccountWithSiteRow): Promise { - const rows = await db.select().from(schema.accounts) - .innerJoin(schema.sites, eq(schema.accounts.siteId, schema.sites.id)).all(); - - const { localDay, startUtc, endUtc } = getLocalDayRangeUtc(); - - // Aggregate today's spend per account from proxy logs - const todaySpendRows = await db.select({ - accountId: schema.proxyLogs.accountId, - totalSpend: sql`coalesce(sum(${schema.proxyLogs.estimatedCost}), 0)`, - }).from(schema.proxyLogs) - .where(and(gte(schema.proxyLogs.createdAt, startUtc), lt(schema.proxyLogs.createdAt, endUtc))) - .groupBy(schema.proxyLogs.accountId) - .all(); - const spendByAccount: Record = {}; - for (const row of todaySpendRows) { - if (row.accountId == null) continue; - spendByAccount[row.accountId] = Number(row.totalSpend || 0); - } - - const modelCountRows = await db.select({ - accountId: schema.modelAvailability.accountId, - modelCount: sql`count(*)`, - }).from(schema.modelAvailability) - .where(eq(schema.modelAvailability.available, true)) - .groupBy(schema.modelAvailability.accountId) - .all(); - const modelCountByAccount: Record = {}; - for (const row of modelCountRows) { - if (row.accountId == null) continue; - modelCountByAccount[row.accountId] = Number(row.modelCount || 0); - } - - // Aggregate today's checkin rewards per account - const todayCheckins = await db.select({ - accountId: schema.checkinLogs.accountId, - reward: schema.checkinLogs.reward, - message: schema.checkinLogs.message, - }).from(schema.checkinLogs) - .where(and( - gte(schema.checkinLogs.createdAt, startUtc), - lt(schema.checkinLogs.createdAt, endUtc), - eq(schema.checkinLogs.status, 'success'), - )) - .all(); - const rewardByAccount: Record = {}; - const successCountByAccount: Record = {}; - const parsedRewardCountByAccount: Record = {}; - for (const log of todayCheckins) { - successCountByAccount[log.accountId] = (successCountByAccount[log.accountId] || 0) + 1; - const rewardNum = parseCheckinRewardAmount(log.reward) || parseCheckinRewardAmount(log.message); - if (rewardNum <= 0) continue; - rewardByAccount[log.accountId] = (rewardByAccount[log.accountId] || 0) + rewardNum; - parsedRewardCountByAccount[log.accountId] = (parsedRewardCountByAccount[log.accountId] || 0) + 1; - } - - return rows.map((r) => { - const credentialMode = resolveStoredCredentialMode(r.accounts); - const capabilities = buildCapabilitiesForAccount(r.accounts); + app.get<{ Querystring: { refresh?: string } }>( + "/api/accounts", + async (request, reply) => { + const snapshot = await getAccountsSnapshot({ + forceRefresh: parseBooleanFlag(request.query.refresh), + }); + reply.header("x-accounts-snapshot-cache", snapshot.cacheStatus); return { - ...r.accounts, - site: r.sites, - credentialMode, - capabilities, - todaySpend: Math.round((spendByAccount[r.accounts.id] || 0) * 1_000_000) / 1_000_000, - todayReward: Math.round(estimateRewardWithTodayIncomeFallback({ - day: localDay, - successCount: successCountByAccount[r.accounts.id] || 0, - parsedRewardCount: parsedRewardCountByAccount[r.accounts.id] || 0, - rewardSum: rewardByAccount[r.accounts.id] || 0, - extraConfig: r.accounts.extraConfig, - }) * 1_000_000) / 1_000_000, - runtimeHealth: buildRuntimeHealthForAccount({ - accountStatus: r.accounts.status, - siteStatus: r.sites.status, - extraConfig: r.accounts.extraConfig, - sessionCapable: capabilities.canRefreshBalance, - hasDiscoveredModels: (modelCountByAccount[r.accounts.id] || 0) > 0, - }), + generatedAt: snapshot.generatedAt, + accounts: snapshot.payload.accounts, + sites: snapshot.payload.sites, }; - }); - }); + }, + ); // Login to a site and auto-create account app.post<{ Body: unknown }>( - '/api/accounts/login', + "/api/accounts/login", { preHandler: [limitAccountLogin] }, async (request, reply) => { - const parsedBody = parseAccountLoginPayload(request.body); - if (!parsedBody.success) { - return reply.code(400).send({ success: false, message: parsedBody.error }); - } + const parsedBody = parseAccountLoginPayload(request.body); + if (!parsedBody.success) { + return reply + .code(400) + .send({ success: false, message: parsedBody.error }); + } - const { siteId, username, password } = parsedBody.data; + const { siteId, username, password } = parsedBody.data; - // Get site info - const site = await db.select().from(schema.sites).where(eq(schema.sites.id, siteId)).get(); - if (!site) return { success: false, message: 'site not found' }; + // Get site info + const site = await db + .select() + .from(schema.sites) + .where(eq(schema.sites.id, siteId)) + .get(); + if (!site) return { success: false, message: "site not found" }; - // Get platform adapter - const adapter = getAdapter(site.platform); - if (!adapter) return { success: false, message: `不支持的平台: ${site.platform}` }; + // Get platform adapter + const adapter = getAdapter(site.platform); + if (!adapter) + return { success: false, message: `不支持的平台: ${site.platform}` }; - // Login to the target site - const loginResult = await adapter.login(site.url, username, password); - if (!loginResult.success || !loginResult.accessToken) { - const normalizedFailure = normalizeLoginFailure(loginResult.message); - return { - success: false, - shieldBlocked: normalizedFailure.shieldBlocked, - message: normalizedFailure.message, - }; - } + // Login to the target site + const loginResult = await adapter.login(site.url, username, password); + if (!loginResult.success || !loginResult.accessToken) { + const normalizedFailure = normalizeLoginFailure(loginResult.message); + return { + success: false, + shieldBlocked: normalizedFailure.shieldBlocked, + message: normalizedFailure.message, + }; + } - const guessedPlatformUserId = guessPlatformUserIdFromUsername(username); + const guessedPlatformUserId = guessPlatformUserIdFromUsername(username); - // Auto-fetch API token(s) - let apiToken: string | null = null; - let apiTokens: Array<{ name?: string | null; key?: string | null; enabled?: boolean | null }> = []; - try { - apiToken = await adapter.getApiToken(site.url, loginResult.accessToken, guessedPlatformUserId); - } catch { } - try { - apiTokens = await adapter.getApiTokens(site.url, loginResult.accessToken, guessedPlatformUserId); - } catch { } + // Auto-fetch API token(s) + let apiToken: string | null = null; + let apiTokens: Array<{ + name?: string | null; + key?: string | null; + enabled?: boolean | null; + }> = []; + try { + apiToken = await adapter.getApiToken( + site.url, + loginResult.accessToken, + guessedPlatformUserId, + ); + } catch {} + try { + apiTokens = await adapter.getApiTokens( + site.url, + loginResult.accessToken, + guessedPlatformUserId, + ); + } catch {} - const preferredApiToken = apiTokens.find((token) => token.enabled !== false && token.key)?.key || apiToken || null; - const existing = await db.select().from(schema.accounts) - .where(and(eq(schema.accounts.siteId, siteId), eq(schema.accounts.username, username))) - .get(); + const preferredApiToken = + apiTokens.find((token) => token.enabled !== false && token.key)?.key || + apiToken || + null; + const existing = await db + .select() + .from(schema.accounts) + .where( + and( + eq(schema.accounts.siteId, siteId), + eq(schema.accounts.username, username), + ), + ) + .get(); - const extraConfigPatch: Record = { - credentialMode: 'session', - autoRelogin: { - username, - passwordCipher: encryptAccountPassword(password), - updatedAt: new Date().toISOString(), - }, - }; - if (guessedPlatformUserId) { - extraConfigPatch.platformUserId = guessedPlatformUserId; - } - const extraConfig = mergeAccountExtraConfig(existing?.extraConfig, extraConfigPatch); - - // Create or update account - let accountId = existing?.id; - if (existing) { - await db.update(schema.accounts).set({ - accessToken: loginResult.accessToken, - apiToken: preferredApiToken || undefined, - checkinEnabled: true, - status: 'active', - extraConfig, - updatedAt: new Date().toISOString(), - }).where(eq(schema.accounts.id, existing.id)).run(); - } else { - const created = await insertAndGetById({ - table: schema.accounts, - idColumn: schema.accounts.id, - values: { - siteId, + const extraConfigPatch: Record = { + credentialMode: "session", + autoRelogin: { username, - accessToken: loginResult.accessToken, - apiToken: preferredApiToken || undefined, - checkinEnabled: true, - extraConfig, - isPinned: false, - sortOrder: await getNextAccountSortOrder(), + passwordCipher: encryptAccountPassword(password), + updatedAt: new Date().toISOString(), }, - insertErrorMessage: 'account create failed', - loadErrorMessage: 'account create failed', + }; + if (guessedPlatformUserId) { + extraConfigPatch.platformUserId = guessedPlatformUserId; + } + const extraConfig = mergeAccountExtraConfig( + existing?.extraConfig, + extraConfigPatch, + ); + + // Create or update account + let accountId = existing?.id; + if (existing) { + await db + .update(schema.accounts) + .set({ + accessToken: loginResult.accessToken, + apiToken: preferredApiToken || undefined, + checkinEnabled: true, + status: "active", + extraConfig, + updatedAt: new Date().toISOString(), + }) + .where(eq(schema.accounts.id, existing.id)) + .run(); + } else { + const created = await insertAndGetById< + typeof schema.accounts.$inferSelect + >({ + table: schema.accounts, + idColumn: schema.accounts.id, + values: { + siteId, + username, + accessToken: loginResult.accessToken, + apiToken: preferredApiToken || undefined, + checkinEnabled: true, + extraConfig, + isPinned: false, + sortOrder: await getNextAccountSortOrder(), + }, + insertErrorMessage: "account create failed", + loadErrorMessage: "account create failed", + }); + accountId = created.id; + } + + const result = await db + .select() + .from(schema.accounts) + .where(eq(schema.accounts.id, accountId!)) + .get(); + if (!result) { + return { success: false, message: "account create failed" }; + } + + await convergeAccountMutation({ + accountId: result.id, + preferredApiToken, + defaultTokenSource: "sync", + upstreamTokens: apiTokens, + refreshBalance: true, + refreshModels: true, + rebuildRoutes: true, + continueOnError: true, }); - accountId = created.id; - } - const result = await db.select().from(schema.accounts).where(eq(schema.accounts.id, accountId!)).get(); - if (!result) { - return { success: false, message: 'account create failed' }; - } - - await convergeAccountMutation({ - accountId: result.id, - preferredApiToken, - defaultTokenSource: 'sync', - upstreamTokens: apiTokens, - refreshBalance: true, - refreshModels: true, - rebuildRoutes: true, - continueOnError: true, - }); - - const account = await db.select().from(schema.accounts).where(eq(schema.accounts.id, result.id)).get(); - return { - success: true, - account, - apiTokenFound: !!preferredApiToken, - tokenCount: apiTokens.length, - reusedAccount: !!existing, - }; + const account = await db + .select() + .from(schema.accounts) + .where(eq(schema.accounts.id, result.id)) + .get(); + return { + success: true, + account, + apiTokenFound: !!preferredApiToken, + tokenCount: apiTokens.length, + reusedAccount: !!existing, + }; }, ); // Verify credentials against a site. app.post<{ Body: unknown }>( - '/api/accounts/verify-token', + "/api/accounts/verify-token", { preHandler: [limitAccountVerifyToken] }, async (request, reply) => { - const parsedBody = parseAccountVerifyTokenPayload(request.body); - if (!parsedBody.success) { - return reply.code(400).send({ success: false, message: parsedBody.error }); - } + const parsedBody = parseAccountVerifyTokenPayload(request.body); + if (!parsedBody.success) { + return reply + .code(400) + .send({ success: false, message: parsedBody.error }); + } - const { siteId, platformUserId } = parsedBody.data; - const accessToken = (parsedBody.data.accessToken || '').trim(); - const credentialMode = resolveRequestedCredentialMode(parsedBody.data.credentialMode); - const site = await db.select().from(schema.sites).where(eq(schema.sites.id, siteId)).get(); - if (!site) return { success: false, message: 'site not found' }; + const { siteId, platformUserId } = parsedBody.data; + const accessToken = (parsedBody.data.accessToken || "").trim(); + const credentialMode = resolveRequestedCredentialMode( + parsedBody.data.credentialMode, + ); + const site = await db + .select() + .from(schema.sites) + .where(eq(schema.sites.id, siteId)) + .get(); + if (!site) return { success: false, message: "site not found" }; - if (!accessToken) { - return { success: false, message: 'Token 不能为空' }; - } + if (!accessToken) { + return { success: false, message: "Token 不能为空" }; + } - const adapter = getAdapter(site.platform); - if (!adapter) return { success: false, message: `不支持的平台: ${site.platform}` }; + const adapter = getAdapter(site.platform); + if (!adapter) + return { success: false, message: `不支持的平台: ${site.platform}` }; - const normalizedPlatform = String(adapter.platformName || site.platform || '').trim().toLowerCase(); - const parsedPlatformUserId = typeof platformUserId === 'number' && Number.isFinite(platformUserId) && platformUserId > 0 - ? Math.trunc(platformUserId) - : undefined; - const hasProvidedUserId = parsedPlatformUserId !== undefined; - const skipRawShieldDetection = normalizedPlatform === 'new-api' || normalizedPlatform === 'anyrouter'; - const diagnoseVerificationFailure = async ( - options: { useApiEndpointPool?: boolean } = {}, - ): Promise => { - const parseFailureReason = (bodyText: string, contentType: string): VerifyFailureReason => { - const text = bodyText || ''; - const ct = (contentType || '').toLowerCase(); - if ( - !skipRawShieldDetection - && ct.includes('text/html') - && /var\s+arg1\s*=|acw_sc__v2|cdn_sec_tc|