docs(gateway): gateway 剩余文件注释改中文(逐行 1:1,代码零字节改动)
主人 2026-10-03 拍板「注释一律中文」;gateway 至此整包注释中文化完成(本会话共 3 批: 已推库 16 个文件 + 本批剩余文件)。 校验:机械校验(非注释改动行)= 空;剥注释后代码文本逐行比对全等(不一致文件数 0); 全树 go test ./... 58 包 ok / 0 FAIL;交叉编译绿。
This commit is contained in:
1 parent
91e8d7a029
commit
074ffc4ebf
73 files changed
+2529
-2529
No files matched your search
+108
-108
@@ -17,11 +17,11 @@ import (
|
||||
"git.yeij.top/AskaEth/Cyrene_v2/pkg/plugins/sdk"
|
||||
)
|
||||
|
||||
// backthinkListLimit is the number of most-recent think records the admin
|
||||
// panel asks for when no limit is specified.
|
||||
// backthinkListLimit 是未指定 limit 时管理面板索取的
|
||||
// 最近 think 记录条数。
|
||||
const backthinkListLimit = 50
|
||||
|
||||
// PluginSummary is the wire shape of a capability/plugin in the admin list.
|
||||
// PluginSummary 是管理列表中一个能力/插件的线上结构。
|
||||
type PluginSummary struct {
|
||||
Name string `json:"name"`
|
||||
Kind string `json:"kind"`
|
||||
@@ -30,14 +30,14 @@ type PluginSummary struct {
|
||||
AllowInStranger bool `json:"allowInStranger"`
|
||||
}
|
||||
|
||||
// ChannelSummary is the wire shape of a registered channel adapter. Accounts
|
||||
// carries that platform's configured accounts (masked, no raw tokens) so the
|
||||
// panel can show and edit the account config; it is omitted when s.channels is
|
||||
// not wired or the platform has no configured account.
|
||||
// ChannelSummary 是一个已注册渠道适配器的线上结构。Accounts
|
||||
// 承载该平台已配置的账号(已脱敏,不含原始 token),使
|
||||
// 面板能展示并编辑账号配置;当 s.channels 未接线
|
||||
// 或该平台没有已配置账号时省略。
|
||||
//
|
||||
// NeedsRescan/LastError (v0.39) report that the adapter needs the owner to
|
||||
// re-authorize it (see rescanAware in admin_channels_rescan.go); both are omitted
|
||||
// unless the adapter really asked for it.
|
||||
// NeedsRescan/LastError(v0.39)报告适配器需要主人重新授权
|
||||
// (见 admin_channels_rescan.go 中的 rescanAware);二者仅在适配器
|
||||
// 确实要求时才出现,否则一律省略。
|
||||
type ChannelSummary struct {
|
||||
Name string `json:"name"`
|
||||
Connected bool `json:"connected"`
|
||||
@@ -46,15 +46,15 @@ type ChannelSummary struct {
|
||||
Accounts []AdminChannelAccount `json:"accounts,omitempty"`
|
||||
}
|
||||
|
||||
// policyRequest is the POST /api/v1/admin/plugins/policy body.
|
||||
// policyRequest 是 POST /api/v1/admin/plugins/policy 的请求体。
|
||||
type policyRequest struct {
|
||||
Name string `json:"name"`
|
||||
AllowInGroup bool `json:"allowInGroup"`
|
||||
AllowInStranger bool `json:"allowInStranger"`
|
||||
}
|
||||
|
||||
// AdminLlmProvider is the wire shape of one LLM provider in the admin config.
|
||||
// The API key is deliberately absent: it is never returned to the client.
|
||||
// AdminLlmProvider 是管理配置中一个 LLM provider 的线上结构。
|
||||
// API key 刻意缺位:它绝不返回给客户端。
|
||||
type AdminLlmProvider struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
@@ -64,20 +64,20 @@ type AdminLlmProvider struct {
|
||||
Multimodal bool `json:"multimodal"`
|
||||
Enabled bool `json:"enabled"`
|
||||
Fallback string `json:"fallback,omitempty"`
|
||||
// MaxTokens is the group's own token budget (0 = unset; the runtime then
|
||||
// falls back to LLM_FALLBACK_MAX_TOKENS on the last fallback step, then the
|
||||
// adapter default).
|
||||
// MaxTokens 是该分组自身的 token 预算(0 = 未设置;此时运行时
|
||||
// 在最后一个 fallback 步骤回退到 LLM_FALLBACK_MAX_TOKENS,
|
||||
// 再回退到适配器默认值)。
|
||||
MaxTokens int `json:"maxTokens,omitempty"`
|
||||
}
|
||||
|
||||
// AdminLlmConfig is the wire shape of GET /api/v1/admin/llm.
|
||||
// AdminLlmConfig 是 GET /api/v1/admin/llm 的线上结构。
|
||||
type AdminLlmConfig struct {
|
||||
Providers []AdminLlmProvider `json:"providers"`
|
||||
}
|
||||
|
||||
// AdminAutomationRecord is the wire shape of one automation/reminder in the
|
||||
// admin list. Cron carries the cron expression for the cron kind; lastRun and
|
||||
// nextRun are omitted when the value is unknown.
|
||||
// AdminAutomationRecord 是管理列表中一条自动化/提醒的线上结构。
|
||||
// 对 cron 类型,Cron 承载 cron 表达式;lastRun 与
|
||||
// nextRun 在值未知时省略。
|
||||
type AdminAutomationRecord struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
@@ -88,7 +88,7 @@ type AdminAutomationRecord struct {
|
||||
NextRun string `json:"nextRun,omitempty"`
|
||||
}
|
||||
|
||||
// AdminUserRecord is the wire shape of one account/API key in the admin list.
|
||||
// AdminUserRecord 是管理列表中一个账号/API key 的线上结构。
|
||||
type AdminUserRecord struct {
|
||||
ID string `json:"id"`
|
||||
Username string `json:"username"`
|
||||
@@ -96,8 +96,8 @@ type AdminUserRecord struct {
|
||||
CreatedAt string `json:"createdAt,omitempty"`
|
||||
}
|
||||
|
||||
// AdminBackthinkItem is the wire shape of one background-think record in the
|
||||
// admin monitor list.
|
||||
// AdminBackthinkItem 是管理监控列表中一条后台思考记录的
|
||||
// 线上结构。
|
||||
type AdminBackthinkItem struct {
|
||||
ID string `json:"id"`
|
||||
Trigger string `json:"trigger"`
|
||||
@@ -107,17 +107,17 @@ type AdminBackthinkItem struct {
|
||||
At int64 `json:"at"`
|
||||
}
|
||||
|
||||
// adminListPersonas lists persona summaries (admin read). It is the admin shape:
|
||||
// the role-level mood plus the `thinking` knobs the panel edits.
|
||||
// adminListPersonas 列出人格摘要(管理读)。它是管理侧结构:
|
||||
// 角色级 mood 加上面板可编辑的 `thinking` 开关。
|
||||
func (s *Server) adminListPersonas(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusOK, s.collectPersonas(true))
|
||||
}
|
||||
|
||||
// adminListSessions lists the persistent chat-history sessions (main + sub) when a
|
||||
// history store is wired, otherwise falls back to the channel-session view. It is
|
||||
// the admin counterpart of handleListSessions: the panel shows the real main and
|
||||
// secondary sessions (design/16 §2) rather than stale channel-session rows, and
|
||||
// the fallback keeps the pre-design/16 contract for servers built without history.
|
||||
// adminListSessions 在接线了 history store 时列出持久化聊天历史
|
||||
// 会话(main + sub),否则回退到渠道会话视图。它是
|
||||
// handleListSessions 的管理侧对应物:面板展示真实的 main 与
|
||||
// 次级会话(design/16 §2),而不是陈旧的渠道会话行;
|
||||
// 回退路径为未接 history 的服务器保留 design/16 之前的契约。
|
||||
func (s *Server) adminListSessions(w http.ResponseWriter, r *http.Request) {
|
||||
if s.history != nil {
|
||||
s.handleHistorySessions(w, r)
|
||||
@@ -126,12 +126,12 @@ func (s *Server) adminListSessions(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusOK, s.collectSessions(r.Context()))
|
||||
}
|
||||
|
||||
// adminListMemories lists memory entries (admin read).
|
||||
// adminListMemories 列出记忆条目(管理读)。
|
||||
func (s *Server) adminListMemories(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusOK, s.collectMemories(r.Context()))
|
||||
}
|
||||
|
||||
// adminListPlugins lists every registered capability (admin read).
|
||||
// adminListPlugins 列出所有已注册能力(管理读)。
|
||||
func (s *Server) adminListPlugins(w http.ResponseWriter, r *http.Request) {
|
||||
out := make([]PluginSummary, 0)
|
||||
if s.caps != nil {
|
||||
@@ -148,9 +148,9 @@ func (s *Server) adminListPlugins(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusOK, out)
|
||||
}
|
||||
|
||||
// adminListChannels lists the registered channel adapters (admin read). When the
|
||||
// channel config store is wired it also attaches each platform's configured
|
||||
// accounts, masked so a raw token never reaches the client.
|
||||
// adminListChannels 列出已注册的渠道适配器(管理读)。当接线了
|
||||
// 渠道配置存储时,它还会附上各平台已配置的账号,并做脱敏,
|
||||
// 确保原始 token 绝不抵达客户端。
|
||||
func (s *Server) adminListChannels(w http.ResponseWriter, r *http.Request) {
|
||||
accountsByPlatform := s.maskedChannelAccounts()
|
||||
botByPlatform := s.liveBotIdentity()
|
||||
@@ -162,26 +162,26 @@ func (s *Server) adminListChannels(w http.ResponseWriter, r *http.Request) {
|
||||
continue
|
||||
}
|
||||
platform, acctID := splitAdapterName(ch.Name())
|
||||
// channels.json is the source of truth for which accounts exist. A
|
||||
// registered adapter surfaces only while its account is still
|
||||
// configured, so a deleted account disappears from the list. Without a
|
||||
// config store (tests) every registered adapter is listed unchanged.
|
||||
// channels.json 是「存在哪些账号」的唯一事实来源。已注册的
|
||||
// 适配器只有在其账号仍处于配置状态时才浮现,因此已删除的
|
||||
// 账号会从列表中消失。没有配置存储时(测试),每个已注册
|
||||
// 适配器原样列出。
|
||||
if s.channels != nil {
|
||||
accts, ok := accountsByPlatform[platform]
|
||||
if !ok || !platformHasAccountID(accts, acctID) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
// Aggregate by platform: a bare adapter ("kook") and the multi-account
|
||||
// ones ("kook:fc2048", "kook:conf1") are ONE platform row, so the account
|
||||
// list is not duplicated into a separate row per in-registry adapter.
|
||||
// 按平台聚合:裸适配器("kook")与多账号适配器
|
||||
// ("kook:fc2048"、"kook:conf1")共用一个平台行,
|
||||
// 因此账号列表不会按注册表中的每个适配器重复成独立行。
|
||||
if s.hasChannelSummary(out, platform) {
|
||||
continue
|
||||
}
|
||||
sum := ChannelSummary{Name: platform, Connected: ch.IsConnected()}
|
||||
// Optional rescan capability (weixin-iLink rejected session, v0.39): reported
|
||||
// only when the adapter really asks for a re-scan, so a healthy adapter
|
||||
// keeps the fields omitted rather than shipping a fabricated value.
|
||||
// 可选的 rescan 能力(weixin-iLink 会话被拒,v0.39):仅在适配器
|
||||
// 确实要求重新扫码时才报告,因此健康的适配器保持字段省略,
|
||||
// 而不是送出一个编造的值。
|
||||
if ra, ok := asRescanAware(cap.Value); ok {
|
||||
if required, reason := ra.RescanRequired(); required {
|
||||
sum.NeedsRescan = true
|
||||
@@ -194,8 +194,8 @@ func (s *Server) adminListChannels(w http.ResponseWriter, r *http.Request) {
|
||||
out = append(out, sum)
|
||||
}
|
||||
}
|
||||
// A platform that has configured accounts but no registered adapter (e.g. the
|
||||
// account was just saved) still surfaces, so its config is visible.
|
||||
// 有已配置账号但没有已注册适配器的平台(例如账号刚刚保存)
|
||||
// 依然会浮现,以便其配置可见。
|
||||
for platform, accts := range accountsByPlatform {
|
||||
if len(accts) == 0 || s.hasChannelSummary(out, platform) {
|
||||
continue
|
||||
@@ -205,8 +205,8 @@ func (s *Server) adminListChannels(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusOK, out)
|
||||
}
|
||||
|
||||
// maskedChannelAccounts returns the effective per-platform configured accounts,
|
||||
// masked (no raw tokens). It is empty when the channel config store is not wired.
|
||||
// maskedChannelAccounts 返回按平台生效的已配置账号,
|
||||
// 已脱敏(不含原始 token)。渠道配置存储未接线时为空。
|
||||
func (s *Server) maskedChannelAccounts() map[string][]AdminChannelAccount {
|
||||
if s.channels == nil {
|
||||
return map[string][]AdminChannelAccount{}
|
||||
@@ -229,9 +229,9 @@ func (s *Server) maskedChannelAccounts() map[string][]AdminChannelAccount {
|
||||
return out
|
||||
}
|
||||
|
||||
// platformAdminOps returns the account-level admin operations the platform's
|
||||
// adapter exposes, so the panel renders only the capabilities the account really
|
||||
// has. Platforms without a specialized adapter surface return nil (omitted).
|
||||
// platformAdminOps 返回该平台适配器暴露的账号级管理操作,
|
||||
// 使面板只渲染账号真正具备的能力。没有专用适配器
|
||||
// 表面的平台返回 nil(省略)。
|
||||
func platformAdminOps(platform string) []string {
|
||||
if channelBasePlatform(platform) == "kook" {
|
||||
return []string{"friends", "user_chats", "channels", "guilds", "message_test"}
|
||||
@@ -239,8 +239,8 @@ func platformAdminOps(platform string) []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
// hasChannelSummary reports whether out already contains a summary for platform
|
||||
// (so a platform with a registered adapter is not duplicated).
|
||||
// hasChannelSummary 报告 out 中是否已含该平台的摘要
|
||||
// (以免有已注册适配器的平台被重复)。
|
||||
func (s *Server) hasChannelSummary(out []ChannelSummary, platform string) bool {
|
||||
for _, c := range out {
|
||||
if channelBasePlatform(c.Name) == platform {
|
||||
@@ -250,11 +250,11 @@ func (s *Server) hasChannelSummary(out []ChannelSummary, platform string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// platformHasAccountID reports whether the configured accounts of a platform still
|
||||
// include the account an adapter is bound to. A bare adapter (kook) binds to that
|
||||
// platform's default account (empty id); a multi-account adapter (kook:conf0)
|
||||
// binds to exactly that account id. A mismatch means the adapter is stale — its
|
||||
// account was deleted from channels.json — so it must not surface in the list.
|
||||
// platformHasAccountID 报告某平台已配置的账号中是否仍包含
|
||||
// 适配器所绑定的账号。裸适配器(kook)绑定到该平台的
|
||||
// 默认账号(空 id);多账号适配器(kook:conf0)绑定到
|
||||
// 恰好那个账号 id。不匹配意味着适配器已陈旧 —— 它的
|
||||
// 账号已从 channels.json 删除 —— 因此不得出现在列表中。
|
||||
func platformHasAccountID(accts []AdminChannelAccount, id string) bool {
|
||||
for _, a := range accts {
|
||||
if a.ID == id {
|
||||
@@ -264,22 +264,22 @@ func platformHasAccountID(accts []AdminChannelAccount, id string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// botInfo is the live, connected bot's resolved identity (kook fetches it from
|
||||
// /api/v3/user/me on Connect). It is surfaced through the adapter's Config() so
|
||||
// the admin list can show who the bot is without persisting it.
|
||||
// botInfo 是已连接机器人的实际解析身份(kook 在 Connect 时从
|
||||
// /api/v3/user/me 获取)。它通过适配器的 Config() 浮现,
|
||||
// 使管理列表能展示机器人是谁而无需持久化。
|
||||
type botInfo struct {
|
||||
id string
|
||||
username string
|
||||
nickname string
|
||||
}
|
||||
|
||||
// empty reports whether no part of the bot identity resolved.
|
||||
// empty 报告机器人身份是否没有任何部分解析成功。
|
||||
func (b botInfo) empty() bool { return b.id == "" && b.username == "" && b.nickname == "" }
|
||||
|
||||
// liveBotIdentity collects the bot identity each registered channel adapter
|
||||
// reports, keyed by bare platform then account id (a bare adapter name yields an
|
||||
// empty account id). Adapters that do not expose bot identity (telegram,
|
||||
// webhook, ...) contribute nothing, so other platforms are unaffected.
|
||||
// liveBotIdentity 收集每个已注册渠道适配器报告的机器人身份,
|
||||
// 以裸平台名再按账号 id 为键(裸适配器名得到空账号 id)。
|
||||
// 不暴露机器人身份的适配器(telegram、webhook……)不贡献
|
||||
// 任何内容,因此其他平台不受影响。
|
||||
func (s *Server) liveBotIdentity() map[string]map[string]botInfo {
|
||||
out := make(map[string]map[string]botInfo)
|
||||
if s.caps == nil {
|
||||
@@ -303,9 +303,9 @@ func (s *Server) liveBotIdentity() map[string]map[string]botInfo {
|
||||
return out
|
||||
}
|
||||
|
||||
// botIdentityOf reads the optional bot-identity fields off an adapter config map.
|
||||
// The keys are non-sensitive (bot_id / bot_username / bot_nickname) so they are
|
||||
// never masked by runtimeconfig.Masked.
|
||||
// botIdentityOf 从适配器配置 map 中读取可选的机器人身份字段。
|
||||
// 这些键是非敏感的(bot_id / bot_username / bot_nickname),因此
|
||||
// 绝不会被 runtimeconfig.Masked 脱敏。
|
||||
func botIdentityOf(cfg map[string]any) botInfo {
|
||||
if cfg == nil {
|
||||
return botInfo{}
|
||||
@@ -317,8 +317,8 @@ func botIdentityOf(cfg map[string]any) botInfo {
|
||||
return b
|
||||
}
|
||||
|
||||
// splitAdapterName splits a (possibly multi-account) adapter name like
|
||||
// "kook:conf0" into ("kook", "conf0"); a bare name yields an empty account id.
|
||||
// splitAdapterName 把形如 "kook:conf0" 的(可能多账号的)适配器名
|
||||
// 拆成 ("kook", "conf0");裸名得到空账号 id。
|
||||
func splitAdapterName(name string) (platform, acct string) {
|
||||
if base, tail, ok := strings.Cut(name, ":"); ok {
|
||||
return base, tail
|
||||
@@ -326,10 +326,10 @@ func splitAdapterName(name string) (platform, acct string) {
|
||||
return name, ""
|
||||
}
|
||||
|
||||
// enrichAccountsWithBot merges the live bot identity into the matching account(s)
|
||||
// of a platform. An account is matched to its live adapter by id, so a
|
||||
// multi-account platform shows each bot's own identity. Accounts without a live
|
||||
// bot (not connected yet) keep their stored fields unchanged.
|
||||
// enrichAccountsWithBot 把实时机器人身份合并进平台中匹配的账号。
|
||||
// 账号按 id 与其实时适配器配对,因此多账号平台会展示
|
||||
// 各自机器人的身份。没有实时机器人的账号(尚未连接)
|
||||
// 保持其已存字段不变。
|
||||
func enrichAccountsWithBot(accts []AdminChannelAccount, by map[string]botInfo) []AdminChannelAccount {
|
||||
if len(by) == 0 {
|
||||
return accts
|
||||
@@ -346,7 +346,7 @@ func enrichAccountsWithBot(accts []AdminChannelAccount, by map[string]botInfo) [
|
||||
return out
|
||||
}
|
||||
|
||||
// adminListIoT lists IoT devices (admin read).
|
||||
// adminListIoT 列出 IoT 设备(管理读)。
|
||||
func (s *Server) adminListIoT(w http.ResponseWriter, r *http.Request) {
|
||||
out := make([]iotDeviceSummary, 0)
|
||||
if s.iot != nil {
|
||||
@@ -363,10 +363,10 @@ func (s *Server) adminListIoT(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusOK, out)
|
||||
}
|
||||
|
||||
// adminGetLlm returns the LLM provider/model configuration read from the live
|
||||
// provider stack (models.json, falling back to .env). API keys are never
|
||||
// returned — the wire shape carries no key field — so the handler leaks nothing
|
||||
// sensitive.
|
||||
// adminGetLlm 返回从实时 provider 栈读取的 LLM provider/model
|
||||
// 配置(models.json,回退到 .env)。API key 绝不返回 ——
|
||||
// 线上结构中不含 key 字段 —— 因此该 handler
|
||||
// 不泄露任何敏感信息。
|
||||
func (s *Server) adminGetLlm(w http.ResponseWriter, r *http.Request) {
|
||||
groups := s.currentLlmGroups()
|
||||
providers := make([]AdminLlmProvider, 0, len(groups))
|
||||
@@ -386,8 +386,8 @@ func (s *Server) adminGetLlm(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusOK, AdminLlmConfig{Providers: providers})
|
||||
}
|
||||
|
||||
// currentLlmGroups returns the provider groups to display: the live stack's
|
||||
// groups when one is wired, otherwise the env-synthesized single group.
|
||||
// currentLlmGroups 返回要展示的 provider 分组:接线了实时栈时
|
||||
// 用它的分组,否则用由环境变量合成的单一分组。
|
||||
func (s *Server) currentLlmGroups() []runtimeconfig.Group {
|
||||
if s.llm != nil {
|
||||
return s.llm.Groups()
|
||||
@@ -395,8 +395,8 @@ func (s *Server) currentLlmGroups() []runtimeconfig.Group {
|
||||
return runtimeconfig.GroupFromEnv(s.cfg.LLM)
|
||||
}
|
||||
|
||||
// providerDisplayName returns a friendly label for a provider group, using the
|
||||
// vendor name for the two known protocols and the group id otherwise.
|
||||
// providerDisplayName 返回 provider 分组的友好标签:两种已知协议
|
||||
// 用厂商名,其余用分组 id。
|
||||
func providerDisplayName(g runtimeconfig.Group) string {
|
||||
switch g.Provider {
|
||||
case runtimeconfig.ProviderOpenAI:
|
||||
@@ -408,7 +408,7 @@ func providerDisplayName(g runtimeconfig.Group) string {
|
||||
}
|
||||
}
|
||||
|
||||
// adminListAutomations lists automations and reminders (admin read).
|
||||
// adminListAutomations 列出自动化与提醒(管理读)。
|
||||
func (s *Server) adminListAutomations(w http.ResponseWriter, r *http.Request) {
|
||||
out := make([]AdminAutomationRecord, 0)
|
||||
if s.automations != nil {
|
||||
@@ -432,9 +432,9 @@ func (s *Server) adminListAutomations(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusOK, out)
|
||||
}
|
||||
|
||||
// adminListUsers lists accounts and API keys (admin read). Without a wired
|
||||
// UserStore it reports the single configured admin account rather than
|
||||
// fabricating a column of virtual users.
|
||||
// adminListUsers 列出账号与 API key(管理读)。未接线 UserStore 时
|
||||
// 它只报告那一个已配置的管理账号,而不是编造
|
||||
// 一列虚拟用户。
|
||||
func (s *Server) adminListUsers(w http.ResponseWriter, r *http.Request) {
|
||||
out := []AdminUserRecord{{
|
||||
ID: "admin",
|
||||
@@ -453,7 +453,7 @@ func (s *Server) adminListUsers(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusOK, out)
|
||||
}
|
||||
|
||||
// adminListBackthink lists the most recent background-think records (admin read).
|
||||
// adminListBackthink 列出最近的后台思考记录(管理读)。
|
||||
func (s *Server) adminListBackthink(w http.ResponseWriter, r *http.Request) {
|
||||
out := make([]AdminBackthinkItem, 0)
|
||||
if s.backthink == nil {
|
||||
@@ -479,8 +479,8 @@ func (s *Server) adminListBackthink(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusOK, out)
|
||||
}
|
||||
|
||||
// AdminRagDoc is the wire shape of one knowledge-base document (project-index
|
||||
// entry) in the admin RAG list.
|
||||
// AdminRagDoc 是管理 RAG 列表中一个知识库文档(项目索引
|
||||
// 条目)的线上结构。
|
||||
type AdminRagDoc struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
@@ -489,7 +489,7 @@ type AdminRagDoc struct {
|
||||
Embedded bool `json:"embedded"`
|
||||
}
|
||||
|
||||
// AdminRagHit is the wire shape of one RAG retrieval hit.
|
||||
// AdminRagHit 是一条 RAG 检索命中的线上结构。
|
||||
type AdminRagHit struct {
|
||||
DocID string `json:"docId"`
|
||||
DocName string `json:"docName"`
|
||||
@@ -499,22 +499,22 @@ type AdminRagHit struct {
|
||||
Semantic bool `json:"semantic"`
|
||||
}
|
||||
|
||||
// AdminRagResponse is the wire shape of GET /api/v1/admin/rag. Hits is present
|
||||
// only when a query parameter was supplied, so callers distinguish "no search
|
||||
// requested" from "searched and found nothing".
|
||||
// AdminRagResponse 是 GET /api/v1/admin/rag 的线上结构。Hits 仅
|
||||
// 在提供了查询参数时出现,因此调用方能区分「未请求搜索」
|
||||
// 与「搜索了但没找到」。
|
||||
type AdminRagResponse struct {
|
||||
Documents []AdminRagDoc `json:"documents"`
|
||||
Hits []AdminRagHit `json:"hits,omitempty"`
|
||||
}
|
||||
|
||||
// ragQueryRequest is the POST /api/v1/admin/rag/query body.
|
||||
// ragQueryRequest 是 POST /api/v1/admin/rag/query 的请求体。
|
||||
type ragQueryRequest struct {
|
||||
Query string `json:"query"`
|
||||
}
|
||||
|
||||
// adminListRag lists the knowledge-base documents and, when ?query= is present,
|
||||
// returns the matching hits too. Without a wired RagStore it degrades to an empty
|
||||
// list (backward compatible — never a 500).
|
||||
// adminListRag 列出知识库文档,并在带 ?query= 时
|
||||
// 一并返回匹配的命中。未接线 RagStore 时它退化为
|
||||
// 空列表(向后兼容 —— 绝不返回 500)。
|
||||
func (s *Server) adminListRag(w http.ResponseWriter, r *http.Request) {
|
||||
out := AdminRagResponse{Documents: make([]AdminRagDoc, 0)}
|
||||
if s.rag == nil {
|
||||
@@ -540,7 +540,7 @@ func (s *Server) adminListRag(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusOK, out)
|
||||
}
|
||||
|
||||
// adminSearchRag runs a knowledge-base query and returns the matching hits.
|
||||
// adminSearchRag 执行一次知识库查询并返回匹配的命中。
|
||||
func (s *Server) adminSearchRag(w http.ResponseWriter, r *http.Request) {
|
||||
if s.rag == nil {
|
||||
s.auditClaims(r, "rag.query", "error")
|
||||
@@ -566,7 +566,7 @@ func (s *Server) adminSearchRag(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusOK, map[string]any{"query": req.Query, "hits": ragHitsFrom(hits)})
|
||||
}
|
||||
|
||||
// ragDocsFrom maps knowledge docs to their admin wire shape.
|
||||
// ragDocsFrom 把知识文档映射为其管理侧线上结构。
|
||||
func ragDocsFrom(docs []knowledge.Doc) []AdminRagDoc {
|
||||
out := make([]AdminRagDoc, 0, len(docs))
|
||||
for _, d := range docs {
|
||||
@@ -575,7 +575,7 @@ func ragDocsFrom(docs []knowledge.Doc) []AdminRagDoc {
|
||||
return out
|
||||
}
|
||||
|
||||
// ragHitsFrom maps knowledge hits to their admin wire shape.
|
||||
// ragHitsFrom 把知识命中映射为其管理侧线上结构。
|
||||
func ragHitsFrom(hits []knowledge.Hit) []AdminRagHit {
|
||||
out := make([]AdminRagHit, 0, len(hits))
|
||||
for _, h := range hits {
|
||||
@@ -591,8 +591,8 @@ func ragHitsFrom(hits []knowledge.Hit) []AdminRagHit {
|
||||
return out
|
||||
}
|
||||
|
||||
// adminSetPolicy upserts the reachability markers for a capability. It is the
|
||||
// audited admin write example (owner-only, enforced by the route registration).
|
||||
// adminSetPolicy 更新插入某个能力的可达性标记。它是
|
||||
// 带审计的管理写示例(仅 owner,由路由注册强制)。
|
||||
func (s *Server) adminSetPolicy(w http.ResponseWriter, r *http.Request) {
|
||||
var req policyRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
@@ -622,7 +622,7 @@ func (s *Server) adminSetPolicy(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusOK, map[string]any{"name": req.Name, "allowInGroup": req.AllowInGroup, "allowInStranger": req.AllowInStranger})
|
||||
}
|
||||
|
||||
// collectSessions returns a non-nil session slice from the configured store.
|
||||
// collectSessions 从已配置的存储返回非 nil 的会话切片。
|
||||
func (s *Server) collectSessions(ctx context.Context) []SessionSummary {
|
||||
out := make([]SessionSummary, 0)
|
||||
if s.sessions == nil {
|
||||
@@ -639,7 +639,7 @@ func (s *Server) collectSessions(ctx context.Context) []SessionSummary {
|
||||
return out
|
||||
}
|
||||
|
||||
// collectMemories returns a non-nil memory slice from the configured store.
|
||||
// collectMemories 从已配置的存储返回非 nil 的记忆切片。
|
||||
func (s *Server) collectMemories(ctx context.Context) []MemorySummary {
|
||||
out := make([]MemorySummary, 0)
|
||||
if s.memories == nil {
|
||||
@@ -656,7 +656,7 @@ func (s *Server) collectMemories(ctx context.Context) []MemorySummary {
|
||||
return out
|
||||
}
|
||||
|
||||
// iotDeviceSummary is the wire shape of an IoT device.
|
||||
// iotDeviceSummary 是一个 IoT 设备的线上结构。
|
||||
type iotDeviceSummary struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
|
||||
Reference in new issue
Block a user