channel_monitor_request_template.go 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. package schema
  2. import (
  3. "github.com/Wei-Shaw/sub2api/ent/schema/mixins"
  4. "entgo.io/ent"
  5. "entgo.io/ent/dialect/entsql"
  6. "entgo.io/ent/schema"
  7. "entgo.io/ent/schema/edge"
  8. "entgo.io/ent/schema/field"
  9. "entgo.io/ent/schema/index"
  10. )
  11. // ChannelMonitorRequestTemplate 请求模板:一组可复用的 headers + 可选 body 覆盖配置。
  12. //
  13. // 语义为快照:模板被"应用"到监控时,extra_headers / body_override_mode / body_override
  14. // 会被**拷贝**到 channel_monitors 同名字段;后续模板变动不会自动影响已应用的监控——
  15. // 必须用户主动在模板编辑 Dialog 里点「应用到关联监控」才会覆盖快照。
  16. // 这样模板改错不会瞬间打挂所有已经跑起来的监控。
  17. type ChannelMonitorRequestTemplate struct {
  18. ent.Schema
  19. }
  20. func (ChannelMonitorRequestTemplate) Annotations() []schema.Annotation {
  21. return []schema.Annotation{
  22. entsql.Annotation{Table: "channel_monitor_request_templates"},
  23. }
  24. }
  25. func (ChannelMonitorRequestTemplate) Mixin() []ent.Mixin {
  26. return []ent.Mixin{
  27. mixins.TimeMixin{},
  28. }
  29. }
  30. func (ChannelMonitorRequestTemplate) Fields() []ent.Field {
  31. return []ent.Field{
  32. field.String("name").
  33. NotEmpty().
  34. MaxLen(100),
  35. field.Enum("provider").
  36. Values("openai", "anthropic", "gemini", "grok",
  37. "antigravity", "kimi", "zhipu", "deepseek", "minimax"),
  38. field.String("api_mode").
  39. Default("chat_completions").
  40. MaxLen(32).
  41. Comment("OpenAI request protocol: chat_completions or responses; non-OpenAI uses chat_completions"),
  42. field.String("description").
  43. Optional().
  44. Default("").
  45. MaxLen(500),
  46. // extra_headers: 用户自定义 HTTP 头(如 User-Agent 伪装)。
  47. // 运行时 merge 进 adapter 默认 headers,用户值优先;
  48. // hop-by-hop 黑名单(Host/Content-Length/...)由 checker 过滤。
  49. field.JSON("extra_headers", map[string]string{}).
  50. Default(map[string]string{}),
  51. // body_override_mode: 'off' | 'merge' | 'replace'
  52. // off - 用 adapter 默认 body(忽略 body_override)
  53. // merge - adapter 默认 body 与 body_override 浅合并(body_override 优先,
  54. // model/messages/contents 等关键字段在 checker 里走黑名单跳过)
  55. // replace - 直接用 body_override 作为完整 body;此时跳过 challenge 校验,
  56. // 改为 HTTP 2xx + 响应文本非空即视为可用
  57. field.String("body_override_mode").
  58. Default("off").
  59. MaxLen(10),
  60. // body_override: JSON 对象,根据 body_override_mode 使用。
  61. // 用 map[string]any 以便前端传任意结构(含嵌套)。
  62. field.JSON("body_override", map[string]any{}).
  63. Optional(),
  64. }
  65. }
  66. func (ChannelMonitorRequestTemplate) Edges() []ent.Edge {
  67. return []ent.Edge{
  68. edge.From("monitors", ChannelMonitor.Type).
  69. Ref("request_template"),
  70. }
  71. }
  72. func (ChannelMonitorRequestTemplate) Indexes() []ent.Index {
  73. return []ent.Index{
  74. // 同一 provider 内 name 唯一:允许 Anthropic + OpenAI 重名 "伪装官方客户端"。
  75. index.Fields("provider", "name").Unique(),
  76. index.Fields("provider", "api_mode"),
  77. }
  78. }