mirror of
https://github.com/zyycn/codex-proxy-rs.git
synced 2026-11-06 08:06:19 +00:00
refactor(plugin): keep external quota cycles out of host ledger (#332)
Restore the pre-window host implementation and document plugin-owned policy and presentation. Keep native reset RPC coverage and run plugin integration tests with the standard isolated test services. Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
@@ -106,7 +106,7 @@ async fn plugin_process_manages_native_budget_through_client_key_service() {
|
||||
"client_key_id":"key_budget", "daily_limit_usd":"10", "weekly_limit_usd":"20",
|
||||
"daily_used_usd":"3", "weekly_used_usd":"0",
|
||||
"daily_resets_at_ms":before.budget.daily_resets_at.map(|time| chrono::DateTime::<chrono::Utc>::from(time).timestamp_millis()),
|
||||
"weekly_resets_at_ms":before.budget.weekly_resets_at.map(|time| chrono::DateTime::<chrono::Utc>::from(time).timestamp_millis()),
|
||||
"weekly_resets_at_ms":null,
|
||||
});
|
||||
assert_eq!(results[6], expected);
|
||||
assert_eq!(results[7], json!({"client_key_id":"key_budget"}));
|
||||
@@ -126,10 +126,7 @@ async fn plugin_process_manages_native_budget_through_client_key_service() {
|
||||
1
|
||||
);
|
||||
assert_eq!(after.budget.daily_resets_at, before.budget.daily_resets_at);
|
||||
assert_eq!(
|
||||
after.budget.weekly_resets_at,
|
||||
before.budget.weekly_resets_at
|
||||
);
|
||||
assert_eq!(after.budget.weekly_resets_at, None);
|
||||
assert_eq!(audits.len(), 1);
|
||||
assert!(audits[0].starts_with(&format!("plugin:{}:scope:", view.target.instance_id)));
|
||||
}
|
||||
|
||||
@@ -644,8 +644,24 @@ impl Environment {
|
||||
}
|
||||
|
||||
async fn create_with_store_mode(command_line: bool) -> Option<Self> {
|
||||
let database = std::env::var("CPR_PLUGIN_TEST_DATABASE_URL").ok()?;
|
||||
let redis = std::env::var("CPR_PLUGIN_TEST_REDIS_URL").expect("isolated plugin Redis URL");
|
||||
// 插件专用服务优先;CI 的标准测试服务同样通过随机 schema 隔离数据库。
|
||||
let (database, redis) = if let Ok(database) = std::env::var("CPR_PLUGIN_TEST_DATABASE_URL")
|
||||
{
|
||||
(
|
||||
database,
|
||||
std::env::var("CPR_PLUGIN_TEST_REDIS_URL").expect("isolated plugin Redis URL"),
|
||||
)
|
||||
} else {
|
||||
let database = std::env::var("CPR_TEST_DATABASE_URL").ok();
|
||||
assert!(
|
||||
database.is_some() || std::env::var_os("CI").is_none(),
|
||||
"CI requires plugin or standard test services"
|
||||
);
|
||||
(
|
||||
database?,
|
||||
std::env::var("CPR_TEST_REDIS_URL").expect("isolated test Redis URL"),
|
||||
)
|
||||
};
|
||||
let schema = format!("cpr_plugin_{}", uuid::Uuid::new_v4().simple());
|
||||
let admin = PgPoolOptions::new()
|
||||
.max_connections(1)
|
||||
|
||||
@@ -186,6 +186,12 @@ SDK 不自动重试。超时或断连不能证明写入未提交;重试上限
|
||||
不存在的 Key 返回 `rejected`;写入事务复验发现实例停用或版本变化时返回 `conflict`,
|
||||
非法输入返回 `invalid_input`。账号关联、预算分配和重置触发由插件决定,宿主不自动串联上述接口
|
||||
|
||||
插件的外部周期、截止时间和同步进度保存在自身 `host.state.*` 中,并通过自己的管理页面展示;
|
||||
这些数据不会改写宿主日/周窗口及其显示。插件可在 `request` 中间件中按自己的策略提前拒绝请求,
|
||||
在确认新周期后调用预算重置或上限修改接口;调用仍遵循上述原生语义,宿主窗口继续按自身日期规则滚动。
|
||||
私有状态写入与预算操作不是一个事务,不能把私有状态标记当作预算操作已提交的证明;结果未知时须按上述合同处理。
|
||||
停用插件会停止其后续拦截与同步,已执行的额度修改或重置不会自动撤销
|
||||
|
||||
### Key、模型与模型调用
|
||||
|
||||
模型调用方法:
|
||||
|
||||
@@ -53,7 +53,7 @@ impl HostClient {
|
||||
serde_json::from_value(reply.result).map_err(|_| invalid())
|
||||
}
|
||||
|
||||
/// 清零指定周期,保留限额和到期时间;结果未知时不能盲目重试。
|
||||
/// 清零并关闭指定周期,保留限额,下次使用时重新开启;结果未知时不能盲目重试。
|
||||
///
|
||||
/// # Errors
|
||||
/// 实例过期、Key 不存在、宿主写入失败时返回错误。
|
||||
|
||||
@@ -561,7 +561,8 @@ Admin 的手动重置复用同一账本与 Key 行锁,在一个事务中清零
|
||||
插件预算回调通过 `PluginClientKeyAccess` 进入同一 `ClientKeyService` 和 `ClientKeyStore`,存储事务先复核插件实例版本,
|
||||
再执行原生预算操作;不建立另一份预算状态。查询复用账本投影,不触发准入。局部更新金额上限不改用量或窗口,
|
||||
仅在值变化时提交配置 revision、审计并发布;重置仍不推进配置版本。重复调用及结果未知的合同见
|
||||
[SDK 预算接口](../backend/crates/gateway-plugin/sdk/docs/capabilities.md#client-key-预算)
|
||||
[SDK 预算接口](../backend/crates/gateway-plugin/sdk/docs/capabilities.md#client-key-预算)。插件的外部周期和截止时间属于插件私有状态,展示在插件页面;
|
||||
宿主预算接口和管理页面只表达原生窗口事实,不为插件周期修改滚动规则或重置语义
|
||||
|
||||
- 日窗口按北京时间零点划分;七天窗口从首次准入当天零点开始,到期后由下一次使用重新开启,不固定为周一
|
||||
- 金额优先使用 Provider 上报的 USD,否则按现有模型价格估算;订阅账号的估算费用不代表上游订阅账单。
|
||||
@@ -849,7 +850,8 @@ RUST_MIN_STACK=16777216 cargo +1.97.0 test --manifest-path backend/Cargo.toml --
|
||||
其他检查与界面验证按 [贡献与审查](../CONTRIBUTING.md#验证) 执行
|
||||
|
||||
插件 Runtime 的真实子进程与持久化测试使用 `CPR_PLUGIN_TEST_DATABASE_URL` 和
|
||||
`CPR_PLUGIN_TEST_REDIS_URL` 指向专用实例,密码及隔离要求与上述 Store 测试一致。
|
||||
`CPR_PLUGIN_TEST_REDIS_URL` 指向专用实例;未提供插件专用变量时复用 `CPR_TEST_DATABASE_URL` 与 `CPR_TEST_REDIS_URL`。
|
||||
密码及隔离要求与上述 Store 测试一致,CI 缺少服务配置时直接失败。
|
||||
设置 `CPR_PLUGIN_TEST_LIVE_HTTP=1` 会额外请求 GitHub 公共 HTTPS API,验证受管出站链路;这不代表模型推理验收。
|
||||
若测试环境使用 Fake-IP 或私网 DNS,需通过 `CPR_PLUGIN_TEST_LIVE_NETWORK_RANGES` 显式提供逗号分隔的
|
||||
CIDR 授权。该选项只用于真实网络测试,默认为空,不改变生产网络策略或其他测试的授权
|
||||
|
||||
Reference in New Issue
Block a user