Files
Genarrative/server-rs/crates/spacetime-module/src/agc_models.rs
T
suzmii 4234a21eed 服务端:AGC 模型目录缺配置时改为启动期从上游同步,保留原目录格式
- module-runtime:删除写死的初始目录(高质量→gpt-6-astra、快速→gpt-5.6-luna),新增 from_upstream_models:id 用模型名 slug、alias/modelId 用上游原名、默认项取排序后第一项;字段与校验规则不变
- spacetime-module:read_agc_model_catalog 缺行返回 AGC_MODEL_CATALOG_NOT_INITIALIZED,不再返回内置目录
- api-server:新增启动期 ensure_agc_model_catalog_initialized,未初始化时从分组定价列表 GET /api/pricing?group=taonier 生成目录并按存量 revision 写回;拉不到只记录 error、不写替代目录,下次启动重试
- api-server:目录未初始化时 AGC 目录/对话接口与后台目录接口返回 503,不回落任何内置模型名;后台 PUT 同样要求已初始化
- api-server:上游请求 10s 超时、1 MiB 流式上限、禁止重定向、不带凭据;目标校验只校验地址,不再绑定已下线的固定模型哨兵;写回冲突后重读校验既有目录
2026-09-24 16:18:06 +08:00

65 lines
2.3 KiB
Rust

use crate::*;
#[spacetimedb::table(accessor = agc_model_catalog)]
pub struct AgcModelCatalogRow {
#[primary_key]
pub id: u8,
pub catalog_json: String,
pub revision: u64,
pub updated_at: Timestamp,
}
#[spacetimedb::procedure]
pub fn read_agc_model_catalog(ctx: &mut ProcedureContext) -> Result<String, String> {
let caller = ctx.sender();
ctx.try_with_tx(|tx| {
crate::editor_project_storage::require_editor_generation_runtime_service_identity(
tx, caller,
)?;
// 目录只有一份事实来源:上游同步或后台保存。缺行时不得返回任何内置目录,
// 由 api-server 按“未初始化”处理并触发启动期同步。
tx.db
.agc_model_catalog()
.id()
.find(0)
.map(|row| row.catalog_json)
.ok_or_else(|| module_runtime::AGC_MODEL_CATALOG_NOT_INITIALIZED.to_string())
})
}
#[spacetimedb::procedure]
pub fn save_agc_model_catalog(
ctx: &mut ProcedureContext,
catalog_json: String,
) -> Result<String, String> {
let catalog: module_runtime::AgcModelCatalog =
serde_json::from_str(&catalog_json).map_err(|_| "模型目录格式无效".to_string())?;
catalog.validate()?;
let caller = ctx.sender();
ctx.try_with_tx(|tx| {
crate::editor_project_storage::require_editor_generation_runtime_service_identity(
tx, caller,
)?;
let mut catalog = catalog.clone();
let previous = tx.db.agc_model_catalog().id().find(0);
let revision = previous.as_ref().map(|r| r.revision).unwrap_or(0);
if catalog.revision != revision {
return Err(module_runtime::AGC_MODEL_CATALOG_CONFLICT.into());
}
catalog.revision = revision.checked_add(1).ok_or("模型目录版本溢出")?;
let catalog_json = serde_json::to_string(&catalog).map_err(|_| "模型目录序列化失败")?;
let row = AgcModelCatalogRow {
id: 0,
catalog_json: catalog_json.clone(),
revision: catalog.revision,
updated_at: tx.timestamp,
};
if previous.is_some() {
tx.db.agc_model_catalog().id().update(row);
} else {
tx.db.agc_model_catalog().insert(row);
}
Ok(catalog_json)
})
}