compassmock/src/db/schema-ai-config.ts
Nicholai e3b708317c
feat(agent): AI model config with admin controls (#48)
* feat(agent): add AI model config with admin controls

per-user model selection with admin cost ceiling and
toggle. models filter/sort by output token cost. adds
usage tracking, provider icons, and settings UI.

* docs: add openclaw discord integration notes

---------

Co-authored-by: Nicholai <nicholaivogelfilms@gmail.com>
2026-02-06 20:36:31 -07:00

74 lines
2.2 KiB
TypeScript
Executable File

import {
sqliteTable,
text,
integer,
} from "drizzle-orm/sqlite-core"
import { users, agentConversations } from "./schema"
// singleton config row (id = "global")
export const agentConfig = sqliteTable("agent_config", {
id: text("id").primaryKey(),
modelId: text("model_id").notNull(),
modelName: text("model_name").notNull(),
provider: text("provider").notNull(),
promptCost: text("prompt_cost").notNull(),
completionCost: text("completion_cost").notNull(),
contextLength: integer("context_length").notNull(),
maxCostPerMillion: text("max_cost_per_million"),
allowUserSelection: integer("allow_user_selection")
.notNull()
.default(1),
updatedBy: text("updated_by")
.notNull()
.references(() => users.id),
updatedAt: text("updated_at").notNull(),
})
// per-user model preference
export const userModelPreference = sqliteTable(
"user_model_preference",
{
userId: text("user_id")
.primaryKey()
.references(() => users.id),
modelId: text("model_id").notNull(),
promptCost: text("prompt_cost").notNull(),
completionCost: text("completion_cost").notNull(),
updatedAt: text("updated_at").notNull(),
}
)
// one row per streamText invocation
export const agentUsage = sqliteTable("agent_usage", {
id: text("id").primaryKey(),
conversationId: text("conversation_id")
.notNull()
.references(() => agentConversations.id, {
onDelete: "cascade",
}),
userId: text("user_id")
.notNull()
.references(() => users.id),
modelId: text("model_id").notNull(),
promptTokens: integer("prompt_tokens")
.notNull()
.default(0),
completionTokens: integer("completion_tokens")
.notNull()
.default(0),
totalTokens: integer("total_tokens")
.notNull()
.default(0),
estimatedCost: text("estimated_cost").notNull(),
createdAt: text("created_at").notNull(),
})
export type AgentConfig = typeof agentConfig.$inferSelect
export type NewAgentConfig = typeof agentConfig.$inferInsert
export type AgentUsage = typeof agentUsage.$inferSelect
export type NewAgentUsage = typeof agentUsage.$inferInsert
export type UserModelPreference =
typeof userModelPreference.$inferSelect
export type NewUserModelPreference =
typeof userModelPreference.$inferInsert