handler

package
v0.8.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 14, 2026 License: Apache-2.0, MIT Imports: 78 Imported by: 0

Documentation

Overview

Package handler — chunker_debug.go exposes a read-only preview endpoint that runs the adaptive chunker on supplied text without touching the DB or generating embeddings. Used by the KB editor's debug panel so users can experiment with chunking parameters before committing to a re-index.

Index

Constants

View Source
const MCPEndpointPath = "/mcp/"

MCPEndpointPath is the public path prefix the MCP server is mounted on.

Variables

View Source
var (
	Version   = "unknown"
	Edition   = "standard"
	CommitID  = "unknown"
	BuildTime = "unknown"
	GoVersion = "unknown"
)

编译时注入的版本信息

View Source
var DeploymentCapabilityKeys = []string{
	"organizations",
	"agents",
	"integrations.im",
	"integrations.embed",
	"integrations.api",
	"integrations.mcpserver",
	"settings.mcp",
	"settings.websearch",
	"settings.vectorstore",
	"settings.storage",
	"settings.sandbox",
	"settings.sandbox.docker",
	"settings.sandbox.host",
	"settings.sandbox.remote",
}

DeploymentCapabilityKeys is the canonical capability key list shared with frontend/src/config/deploymentCapabilities.ts — keep both in sync.

Functions

func PreviewChunking

func PreviewChunking(c *gin.Context)

PreviewChunking handles POST /chunker/preview. It runs the supplied text through the adaptive chunker and returns the chunks plus diagnostic information about which tier won. Read-only: no DB writes, no embedding calls, no logging of the supplied text.

PreviewChunking godoc @Summary 预览分块结果 @Description 对提交的文本运行自适应分块器并返回分块预览,不写入数据库不生成 embedding。文本最大 64k 字符 @Tags 分块 @Accept json @Produce json @Param request body handler.PreviewChunkingRequest true "{text, chunking_config}" @Success 200 {object} handler.PreviewChunkingResponse "分块结果" @Failure 400 {object} map[string]interface{} "请求参数错误" @Failure 413 {object} map[string]interface{} "文本超过预览限制" @Failure 504 {object} map[string]interface{} "分块超时" @Security Bearer @Security ApiKeyAuth @Router /chunker/preview [post]

func RandomSelect

func RandomSelect(strs []string, n int) []string

RandomSelect selects random strings

func SetHostProjectPicker

func SetHostProjectPicker(fn func() (string, error))

SetHostProjectPicker is called by cmd/desktop. Standard servers leave it nil.

func SetLiteSetupToken

func SetLiteSetupToken(token string)

SetLiteSetupToken is called by the native desktop host before serving requests. Web deployments leave it empty and cannot issue anonymous administrator tokens.

Types

type AddFavoriteRequest

type AddFavoriteRequest struct {
	ResourceType string `json:"type"`
	ResourceID   string `json:"id"`
}

AddFavoriteRequest is the body for POST /user/favorites — kept symmetric with the DELETE path parameters so the frontend can build a single API helper that switches verb on toggle.

type AuditLogHandler

type AuditLogHandler struct {
	// contains filtered or unexported fields
}

AuditLogHandler exposes the per-tenant audit-log feed (PR 6, #1303). The route group lives under /tenants/:id/audit-log, gated by PathTenantMatch (URL :id == active tenant) plus an Admin role requirement — leaks of denied-action histories should not surface to ordinary members.

func NewAuditLogHandler

func NewAuditLogHandler(auditService interfaces.AuditLogService) *AuditLogHandler

NewAuditLogHandler constructs the handler.

func (*AuditLogHandler) ListKnowledgeBaseActivity

func (h *AuditLogHandler) ListKnowledgeBaseActivity(c *gin.Context)

ListKnowledgeBaseActivity returns the durable activity projection for one knowledge base. The route has already resolved KB access; this handler adds an owner-tenant check so organization-shared consumers cannot inspect source workspace actors or configuration history. @Summary 获取知识库活动记录 @Description 返回知识库的重要变更与后台任务入口。仅知识库创建者或所属空间管理员可读,共享空间不可读。 @Tags 知识库 @Produce json @Param id path string true "知识库ID" @Param after_id query int false "游标:返回 id 小于此值的记录" @Param limit query int false "页大小,1-100,默认 50" @Param action query string false "按 action 精确过滤" @Param outcome query string false "按 outcome 精确过滤" @Param actor query string false "按 actor_user_id 精确过滤" @Success 200 {object} auditLogListResponse @Failure 403 {object} errors.AppError @Security Bearer @Router /knowledge-bases/{id}/activity [get]

func (*AuditLogHandler) ListSystemAuditLog

func (h *AuditLogHandler) ListSystemAuditLog(c *gin.Context)

ListSystemAuditLog godoc @Summary 获取平台审计日志 @Description 返回 system-scope(tenant_id=0)的审计事件,覆盖 system.setting_changed / system.admin_promoted / system.admin_revoked 等 SystemAdmin 操作。按 id 倒序的游标分页。 @Tags 审计日志 @Produce json @Param after_id query int false "游标:返回 id 小于此值的记录(默认从最新开始)" @Param limit query int false "页大小,1-100,默认 50" @Param action query string false "按 action 精确过滤(如 system.setting_changed)" @Param outcome query string false "按 outcome 精确过滤(success / denied)" @Param actor query string false "按 actor_user_id 精确过滤" @Success 200 {object} auditLogListResponse @Failure 500 {object} errors.AppError @Security Bearer @Security ApiKeyAuth @Router /system/admin/audit-log [get]

Mounted on /api/v1/system/admin/audit-log under the SystemAdmin() guard. Unlike ListTenantAuditLog this route is *not* tenant-scoped: the system_settings table, admin promote/revoke, and the apply-default-storage-quota bulk write all emit audit rows with tenant_id=0 (see audit_log.go for the action constants). Those rows would never surface in any tenant's audit feed, so this endpoint fixes the "wrote audit, can't see it" gap.

func (*AuditLogHandler) ListTenantAuditLog

func (h *AuditLogHandler) ListTenantAuditLog(c *gin.Context)

ListTenantAuditLog godoc @Summary 获取空间审计日志 @Description 返回该空间最近的审计事件,按 id 倒序。游标分页:将上次响应的 next_cursor 作为下一次请求的 after_id。 @Tags 审计日志 @Produce json @Param id path string true "空间ID" @Param after_id query int false "游标:返回 id 小于此值的记录(默认从最新开始)" @Param limit query int false "页大小,1-100,默认 50" @Param action query string false "按 action 精确过滤(如 rbac.member_added / rbac.access_denied)" @Param outcome query string false "按 outcome 精确过滤(success / denied)" @Param actor query string false "按 actor_user_id 精确过滤" @Success 200 {object} auditLogListResponse @Failure 400 {object} errors.AppError @Security Bearer @Security ApiKeyAuth @Router /tenants/{id}/audit-log [get]

type AuthHandler

type AuthHandler struct {
	// contains filtered or unexported fields
}

AuthHandler implements HTTP request handlers for user authentication Provides functionality for user registration, login, logout, and token management through the REST API endpoints

func NewAuthHandler

func NewAuthHandler(configInfo *config.Config,
	userService interfaces.UserService, tenantService interfaces.TenantService,
	systemSettingSvc interfaces.SystemSettingService,
	invitationSvc interfaces.TenantInvitationService,
) *AuthHandler

NewAuthHandler creates a new auth handler instance with the provided services Parameters:

  • userService: An implementation of the UserService interface for business logic
  • tenantService: An implementation of the TenantService interface for tenant management
  • systemSettingSvc: 3-tier resolver for runtime-tunable settings such as auth.registration_mode (P3). When DB has a row, it overrides cfg's startup value; otherwise we fall back to cfg.Auth.RegistrationMode (which already accounted for the legacy DISABLE_REGISTRATION env coerce during config load). Mismatch impossible by construction since the handler always passes cfg's value as the def parameter to GetString.

Returns a pointer to the newly created AuthHandler

func (*AuthHandler) AutoSetup

func (h *AuthHandler) AutoSetup(c *gin.Context)

@Summary 自动初始化(Lite 桌面版) @Description Lite 版专用:首次启动时自动创建默认用户和空间并返回令牌,首次及后续启动均须通过桌面原生凭据认证,免除手动注册/登录流程 @Tags 认证 @Accept json @Produce json @Success 200 {object} types.LoginResponse @Failure 403 {object} errors.AppError "非 Lite 版本" @Router /auth/auto-setup [post]

func (*AuthHandler) ChangePassword

func (h *AuthHandler) ChangePassword(c *gin.Context)

ChangePassword godoc @Summary 修改密码 @Description 修改当前用户的登录密码。新密码须满足 8–32 位且同时包含字母与数字;开启复杂密码后还需包含大小写与特殊字符。成功后所有会话被撤销,需重新登录。 @Tags 认证 @Accept json @Produce json @Param request body object{old_password=string,new_password=string} true "密码修改请求" @Success 200 {object} map[string]interface{} "修改成功" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Router /auth/change-password [post]

func (*AuthHandler) GetAuthConfig

func (h *AuthHandler) GetAuthConfig(c *gin.Context)

GetAuthConfig godoc @Summary 获取认证配置 @Description 返回当前部署的注册模式与密码复杂度开关,供前端决定是否展示注册入口以及密码校验规则 @Tags 认证 @Accept json @Produce json @Success 200 {object} map[string]interface{} "认证配置" @Router /auth/config [get]

GetAuthConfig is intentionally a no-auth endpoint: the frontend reads it on app load to decide whether to show the Register tab and which password complexity rules to apply. We expose only what the UI strictly needs; other config stays internal.

func (*AuthHandler) GetCurrentUser

func (h *AuthHandler) GetCurrentUser(c *gin.Context)

GetCurrentUser godoc @Summary 获取当前用户信息 @Description 获取当前登录用户的详细信息 @Tags 认证 @Accept json @Produce json @Success 200 {object} map[string]interface{} "用户信息" @Failure 401 {object} errors.AppError "未授权" @Security Bearer @Router /auth/me [get]

func (*AuthHandler) GetOIDCAuthorizationURL

func (h *AuthHandler) GetOIDCAuthorizationURL(c *gin.Context)

GetOIDCAuthorizationURL godoc @Summary 获取OIDC授权地址 @Description 根据后端OIDC配置生成第三方登录跳转地址 @Tags 认证 @Accept json @Produce json @Param redirect_uri query string true "OIDC回调地址" @Success 200 {object} types.OIDCAuthURLResponse @Failure 400 {object} errors.AppError "请求参数错误" @Failure 403 {object} errors.AppError "OIDC未启用" @Router /auth/oidc/url [get]

func (*AuthHandler) GetOIDCConfig

func (h *AuthHandler) GetOIDCConfig(c *gin.Context)

GetOIDCConfig godoc @Summary 获取OIDC登录配置 @Description 返回OIDC是否启用以及provider展示名称,供前端决定是否展示OIDC登录入口 @Tags 认证 @Accept json @Produce json @Success 200 {object} types.OIDCConfigResponse @Router /auth/oidc/config [get]

func (*AuthHandler) Login

func (h *AuthHandler) Login(c *gin.Context)

Login godoc @Summary 用户登录 @Description 用户登录并获取访问令牌 @Tags 认证 @Accept json @Produce json @Param request body types.LoginRequest true "登录请求参数" @Success 200 {object} types.LoginResponse @Failure 401 {object} errors.AppError "认证失败" @Router /auth/login [post]

func (*AuthHandler) Logout

func (h *AuthHandler) Logout(c *gin.Context)

Logout godoc @Summary 用户登出 @Description 撤销当前访问令牌并登出 @Tags 认证 @Accept json @Produce json @Success 200 {object} map[string]interface{} "登出成功" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Router /auth/logout [post]

func (*AuthHandler) LookupInvitationByToken

func (h *AuthHandler) LookupInvitationByToken(c *gin.Context)

LookupInvitationByToken godoc @Summary 解析共享邀请链接 token @Description 根据邀请链接中的 token 返回邀请上下文(空间名 / 角色 / 过期时间), @Description 供注册页展示。无认证;token 无效或被撤销返回 410。 @Description 使用 POST + body 而非 GET + path,避免 token 落入访问日志 / 浏览器历史 / tracing。 @Tags 认证 @Accept json @Produce json @Param request body invitationLookupRequest true "邀请 token" @Success 200 {object} invitationLookupResponse @Failure 410 {object} apperrors.AppError "链接无效或已撤销" @Router /auth/invitations/lookup [post]

func (*AuthHandler) OIDCRedirectCallback

func (h *AuthHandler) OIDCRedirectCallback(c *gin.Context)

OIDCRedirectCallback godoc @Summary OIDC登录重定向回调 @Description 接收OIDC provider回调并由后端完成code交换,随后重定向回前端登录页 @Tags 认证 @Accept json @Produce json @Param code query string false "OIDC授权码" @Param state query string false "OIDC状态" @Param error query string false "OIDC错误码" @Success 302 @Router /auth/oidc/callback [get]

func (*AuthHandler) OIDCStart

func (h *AuthHandler) OIDCStart(c *gin.Context)

OIDCStart godoc @Summary 发起 OIDC 登录(直接 302) @Description 与 /auth/oidc/url 不同,此端点直接 302 重定向到 OIDC Provider 的授权页, @Description 无需前端 JS 介入。适用于外部平台(如企业门户)直接给出一个链接即可 @Description 触发 OIDC 授权码流程,借助 IdP 的 SSO session 实现免再次输密码。 @Tags 认证 @Success 302 @Router /auth/oidc/start [get]

func (*AuthHandler) RefreshToken

func (h *AuthHandler) RefreshToken(c *gin.Context)

RefreshToken godoc @Summary 刷新令牌 @Description 使用刷新令牌获取新的访问令牌 @Tags 认证 @Accept json @Produce json @Param request body object{refreshToken=string} true "刷新令牌" @Success 200 {object} map[string]interface{} "新令牌" @Failure 401 {object} errors.AppError "令牌无效" @Router /auth/refresh [post]

func (*AuthHandler) Register

func (h *AuthHandler) Register(c *gin.Context)

Register godoc @Summary 用户注册 @Description 注册新用户账号 @Tags 认证 @Accept json @Produce json @Param request body types.RegisterRequest true "注册请求参数" @Success 201 {object} types.RegisterResponse @Failure 400 {object} errors.AppError "请求参数错误" @Failure 403 {object} errors.AppError "注册功能已禁用" @Router /auth/register [post]

func (*AuthHandler) RegisterByInvite

func (h *AuthHandler) RegisterByInvite(c *gin.Context)

RegisterByInvite godoc @Summary 使用共享链接注册 @Description 通过共享邀请链接 token 完成注册,仅 self_serve / invite_register 模式允许。 @Description 注册者自填邮箱(与 token 不绑定);注册成功后自动加入对应空间。 @Tags 认证 @Accept json @Produce json @Param request body registerByInviteRequest true "邀请注册请求" @Success 201 {object} types.LoginResponse @Failure 400 {object} apperrors.AppError "请求参数错误" @Failure 403 {object} apperrors.AppError "注册功能已禁用" @Failure 409 {object} apperrors.AppError "邮箱已注册" @Failure 410 {object} apperrors.AppError "链接无效或已撤销" @Router /auth/register-by-invite [post]

RegisterByInvite requires both an enabled registration mode and a valid token.

func (*AuthHandler) SwitchTenant

func (h *AuthHandler) SwitchTenant(c *gin.Context)

SwitchTenant godoc @Summary 切换激活空间 @Description 为当前用户在目标空间重新签发访问令牌;要求该用户在目标空间存在 active 成员关系(跨租户超级用户除外)。 @Description 成功换签会把目标空间写入「最近活跃租户」偏好,下次登录与 refresh 都落在该空间(refresh JWT 不含 tenant_id)。 @Description 该偏好是账号级的:一次换签会改变该用户所有设备的下次登录/refresh 落点。偏好写入失败则整次换签失败,不会发出新 token。 @Tags 认证 @Accept json @Produce json @Param request body object{tenant_id=integer,refresh_token=string} true "切换请求" @Success 200 {object} types.LoginResponse @Failure 400 {object} errors.AppError "参数错误" @Failure 403 {object} errors.AppError "无该空间成员关系或偏好写入失败" @Security Bearer @Router /auth/switch-tenant [post]

SwitchTenant is the v1 backend hook for the tenant-switcher UI added in PR 3. The current PR ships the endpoint so multi-tenant tests can exercise the membership flow end-to-end before the frontend lands.

func (*AuthHandler) UpdateMyPreferences

func (h *AuthHandler) UpdateMyPreferences(c *gin.Context)

UpdateMyPreferences godoc @Summary 更新当前用户的个性化设置 @Description 按 PATCH 语义合并用户偏好(仅覆盖请求体里出现的字段,其余字段保持不变), @Description 数据存放在 users.preferences (JSON),跨设备/浏览器自动同步。 @Tags 认证 @Accept json @Produce json @Param request body updateMyPreferencesRequest true "Preferences patch" @Success 200 {object} map[string]interface{} "更新后的偏好" @Failure 400 {object} errors.AppError "请求参数错误" @Failure 401 {object} errors.AppError "未授权" @Security Bearer @Router /auth/me/preferences [put]

func (*AuthHandler) ValidateToken

func (h *AuthHandler) ValidateToken(c *gin.Context)

ValidateToken godoc @Summary 验证令牌 @Description 验证访问令牌是否有效 @Tags 认证 @Accept json @Produce json @Success 200 {object} map[string]interface{} "令牌有效" @Failure 401 {object} errors.AppError "令牌无效" @Security Bearer @Router /auth/validate [get]

type BatchDeleteKnowledgeRequest

type BatchDeleteKnowledgeRequest struct {
	KBID string   `json:"kb_id" binding:"required"`
	IDs  []string `json:"ids"  binding:"required"`
}

BatchDeleteKnowledgeRequest is the body schema for POST /knowledge/batch-delete.

type BatchDownloadKnowledgeRequest

type BatchDownloadKnowledgeRequest struct {
	IDs []string `json:"ids" binding:"required,min=1,max=200,dive,required,max=128"`
}

BatchDownloadKnowledgeRequest 指定同一知识库中需要下载的文档。

type ChunkHandler

type ChunkHandler struct {
	// contains filtered or unexported fields
}

ChunkHandler defines HTTP handlers for chunk operations.

All KB-access checks (own / org-shared / via shared agent) are now performed by the route-level g.KBAccessRead*FromKnowledgeIDParam / g.KBAccessWrite*FromKnowledgeIDParam / g.KBAccess*FromChunkIDParam guards in router.go — the guard rewrites c.Request.Context() to carry the effective tenant ID, so the handler reads tenant from context the way it always did.

kgService is retained because the route-level *creator-ownership* lookup KBCreatorLookupFromKnowledgeIDParam still walks knowledge_id -> kb_id to resolve creator_id (separate axis from access — that lookup answers "is the caller the creator of THIS resource", not "does the caller's tenant have access").

func NewChunkHandler

func NewChunkHandler(service interfaces.ChunkService, kgService interfaces.KnowledgeService) *ChunkHandler

NewChunkHandler creates a new chunk handler.

func (*ChunkHandler) DeleteChunk

func (h *ChunkHandler) DeleteChunk(c *gin.Context)

DeleteChunk godoc @Summary 删除分块 @Description 删除指定的分块 @Tags 分块管理 @Accept json @Produce json @Param knowledge_id path string true "知识ID" @Param id path string true "分块ID" @Success 200 {object} map[string]interface{} "删除成功" @Failure 400 {object} errors.AppError "请求参数错误" @Failure 404 {object} errors.AppError "分块不存在" @Security Bearer @Security ApiKeyAuth @Router /chunks/{knowledge_id}/{id} [delete]

func (*ChunkHandler) DeleteChunksByKnowledgeID

func (h *ChunkHandler) DeleteChunksByKnowledgeID(c *gin.Context)

DeleteChunksByKnowledgeID godoc @Summary 删除知识下所有分块 @Description 删除指定知识下的所有分块 @Tags 分块管理 @Accept json @Produce json @Param knowledge_id path string true "知识ID" @Success 200 {object} map[string]interface{} "删除成功" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /chunks/{knowledge_id} [delete]

func (*ChunkHandler) DeleteGeneratedQuestion

func (h *ChunkHandler) DeleteGeneratedQuestion(c *gin.Context)

DeleteGeneratedQuestion godoc @Summary 删除生成的问题 @Description 删除分块中生成的问题 @Tags 分块管理 @Accept json @Produce json @Param id path string true "分块ID" @Param request body object{question_id=string} true "问题ID" @Success 200 {object} map[string]interface{} "删除成功" @Failure 400 {object} errors.AppError "请求参数错误" @Failure 404 {object} errors.AppError "分块不存在" @Security Bearer @Security ApiKeyAuth @Router /chunks/by-id/{id}/questions [delete]

func (*ChunkHandler) GetChunkByIDOnly

func (h *ChunkHandler) GetChunkByIDOnly(c *gin.Context)

GetChunkByIDOnly godoc @Summary 通过ID获取分块 @Description 仅通过分块ID获取分块详情(不需要knowledge_id);支持共享知识库下的分块访问 @Tags 分块管理 @Accept json @Produce json @Param id path string true "分块ID" @Success 200 {object} map[string]interface{} "分块详情" @Failure 400 {object} errors.AppError "请求参数错误" @Failure 404 {object} errors.AppError "分块不存在" @Security Bearer @Security ApiKeyAuth @Router /chunks/by-id/{id} [get]

func (*ChunkHandler) KBCreatorLookupFromChunkIDParam

func (h *ChunkHandler) KBCreatorLookupFromChunkIDParam(c *gin.Context) (string, error)

KBCreatorLookupFromChunkIDParam resolves :id (a chunk ID) to the CreatorID of the *owning KB*. The chain is:

chunk_id  -> chunk.KnowledgeID  -> kb_id  -> KB.CreatorID

Used by chunks.DELETE("/by-id/:id/questions") so generated-question deletion follows the same OwnedKBOrAdmin matrix as every other chunk-level mutation, instead of the looser "any Contributor in the tenant" gate. The tenant scope is re-checked explicitly here even though the underlying GetChunkByIDOnly is unscoped — same defence- in-depth pattern as KBCreatorLookup.

func (*ChunkHandler) KBCreatorLookupFromKnowledgeIDParam

func (h *ChunkHandler) KBCreatorLookupFromKnowledgeIDParam(c *gin.Context) (string, error)

KBCreatorLookupFromKnowledgeIDParam mirrors KBCreatorLookupFromKnowledgeID for chunk routes that use :knowledge_id rather than :id. Chunk routes addressed by :id (no knowledge id) instead use KBCreatorLookupFromChunkIDParam below.

func (*ChunkHandler) ListChunkRevisions

func (h *ChunkHandler) ListChunkRevisions(c *gin.Context)

func (*ChunkHandler) ListKnowledgeChunks

func (h *ChunkHandler) ListKnowledgeChunks(c *gin.Context)

ListKnowledgeChunks godoc @Summary 获取知识分块列表 @Description 获取指定知识下的所有分块列表,支持分页 @Tags 分块管理 @Accept json @Produce json @Param knowledge_id path string true "知识ID" @Param page query int false "页码" default(1) @Param page_size query int false "每页数量" default(10) @Success 200 {object} map[string]interface{} "分块列表" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /chunks/{knowledge_id} [get]

func (*ChunkHandler) RegenerateGeneratedQuestions

func (h *ChunkHandler) RegenerateGeneratedQuestions(c *gin.Context)

func (*ChunkHandler) RevertChunk

func (h *ChunkHandler) RevertChunk(c *gin.Context)

func (*ChunkHandler) UpdateChunk

func (h *ChunkHandler) UpdateChunk(c *gin.Context)

UpdateChunk godoc @Summary 更新分块 @Description 更新指定分块的内容和属性 @Tags 分块管理 @Accept json @Produce json @Param knowledge_id path string true "知识ID" @Param id path string true "分块ID" @Param request body UpdateChunkRequest true "更新请求" @Success 200 {object} map[string]interface{} "更新后的分块" @Failure 400 {object} errors.AppError "请求参数错误" @Failure 404 {object} errors.AppError "分块不存在" @Security Bearer @Security ApiKeyAuth @Router /chunks/{knowledge_id}/{id} [put]

func (*ChunkHandler) UpsertGeneratedQuestion

func (h *ChunkHandler) UpsertGeneratedQuestion(c *gin.Context)

type CopyKnowledgeBaseRequest

type CopyKnowledgeBaseRequest struct {
	TaskID   string `json:"task_id"`
	SourceID string `json:"source_id" binding:"required"`
	TargetID string `json:"target_id"`
}

type CopyKnowledgeBaseResponse

type CopyKnowledgeBaseResponse struct {
	TaskID   string `json:"task_id"`
	SourceID string `json:"source_id"`
	TargetID string `json:"target_id"`
	Message  string `json:"message"`
}

CopyKnowledgeBaseResponse defines the response for copy knowledge base

type CopyModelRequest

type CopyModelRequest struct {
	DisplayName string `json:"display_name" binding:"required"`
}

CopyModelRequest is the body of POST /models/:id/copy. Only the display name is client-supplied. The model name and credentials come from the stored source row.

type CreateAgentRequest

type CreateAgentRequest struct {
	Name        string                  `json:"name" binding:"required"`
	Description string                  `json:"description"`
	Avatar      string                  `json:"avatar"`
	Config      types.CustomAgentConfig `json:"config"`
}

CreateAgentRequest defines the request body for creating an agent

type CreateModelRequest

type CreateModelRequest struct {
	Name        string                `json:"name"        binding:"required"`
	DisplayName string                `json:"display_name"`
	Type        types.ModelType       `json:"type"        binding:"required"`
	Source      types.ModelSource     `json:"source"      binding:"required"`
	Description string                `json:"description"`
	Parameters  types.ModelParameters `json:"parameters"  binding:"required"`
}

CreateModelRequest defines the structure for model creation requests Contains all fields required to create a new model in the system

type CreateProviderRequest

type CreateProviderRequest struct {
	Name        string                            `json:"name" binding:"required"`
	Provider    types.WebSearchProviderType       `json:"provider" binding:"required"`
	Description string                            `json:"description"`
	Parameters  types.WebSearchProviderParameters `json:"parameters"`
	IsDefault   bool                              `json:"is_default"`
}

CreateProviderRequest defines the request body for creating a provider

type CreateStoreRequest

type CreateStoreRequest struct {
	Name             string                    `json:"name" binding:"required"`
	EngineType       types.RetrieverEngineType `json:"engine_type" binding:"required"`
	ConnectionConfig types.ConnectionConfig    `json:"connection_config" binding:"required"`
	IndexConfig      types.IndexConfig         `json:"index_config"`
}

CreateStoreRequest defines the request body for creating a vector store

type CreateSystemUserResponse

type CreateSystemUserResponse struct {
	User *types.UserInfo `json:"user"`
	// GeneratedPassword is the plaintext password when the server
	// auto-generated one. Absent when the caller supplied the password.
	GeneratedPassword string `json:"generated_password,omitempty"`
}

CreateSystemUserResponse is the payload returned by POST /api/v1/system/admin/users/create. GeneratedPassword is populated exactly once, only when the server minted a random password (`password` omitted or null), and is never logged, audited, or retrievable again.

type CustomAgentHandler

type CustomAgentHandler struct {
	// contains filtered or unexported fields
}

CustomAgentHandler defines the HTTP handler for custom agent operations

func NewCustomAgentHandler

NewCustomAgentHandler creates a new custom agent handler instance

func (*CustomAgentHandler) AgentCreatorLookup

func (h *CustomAgentHandler) AgentCreatorLookup(c *gin.Context) (string, error)

AgentCreatorLookup resolves :id -> CustomAgent.CreatedBy. Built-in agents (IsBuiltin == true) are tenant-owned across the board: they belong to the tenant rather than to any one user, so we return ("", nil) and let the role check decide. The same holds for legacy rows whose CreatedBy was never populated.

The underlying GetAgentByID already scopes to the caller's tenant, but we keep an explicit defence-in-depth check here in case future refactors loosen the service-layer scope.

func (*CustomAgentHandler) CopyAgent

func (h *CustomAgentHandler) CopyAgent(c *gin.Context)

CopyAgent godoc @Summary 复制智能体 @Description 复制指定的智能体 @Tags 智能体 @Accept json @Produce json @Param id path string true "智能体ID" @Success 201 {object} map[string]interface{} "复制成功" @Failure 400 {object} errors.AppError "请求参数错误" @Failure 404 {object} errors.AppError "智能体不存在" @Security Bearer @Security ApiKeyAuth @Router /agents/{id}/copy [post]

func (*CustomAgentHandler) CreateAgent

func (h *CustomAgentHandler) CreateAgent(c *gin.Context)

CreateAgent godoc @Summary 创建智能体 @Description 创建新的自定义智能体 @Tags 智能体 @Accept json @Produce json @Param request body CreateAgentRequest true "智能体信息" @Success 201 {object} map[string]interface{} "创建的智能体" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /agents [post]

func (*CustomAgentHandler) DeleteAgent

func (h *CustomAgentHandler) DeleteAgent(c *gin.Context)

DeleteAgent godoc @Summary 删除智能体 @Description 删除指定的智能体 @Tags 智能体 @Accept json @Produce json @Param id path string true "智能体ID" @Success 200 {object} map[string]interface{} "删除成功" @Failure 400 {object} errors.AppError "请求参数错误" @Failure 403 {object} errors.AppError "无法删除内置智能体" @Failure 404 {object} errors.AppError "智能体不存在" @Security Bearer @Security ApiKeyAuth @Router /agents/{id} [delete]

func (*CustomAgentHandler) GetAgent

func (h *CustomAgentHandler) GetAgent(c *gin.Context)

GetAgent godoc @Summary 获取智能体详情 @Description 根据ID获取智能体详情 @Tags 智能体 @Accept json @Produce json @Param id path string true "智能体ID" @Success 200 {object} map[string]interface{} "智能体详情" @Failure 400 {object} errors.AppError "请求参数错误" @Failure 404 {object} errors.AppError "智能体不存在" @Security Bearer @Security ApiKeyAuth @Router /agents/{id} [get]

func (*CustomAgentHandler) GetAgentTools

func (h *CustomAgentHandler) GetAgentTools(c *gin.Context)

GetAgentTools godoc @Summary 获取智能体可选工具 @Description 返回编辑器可勾选的内置工具(含分组和知识库能力要求)、工具列表未设置时生效的默认工具,以及由开关控制、写入工具列表也不生效的工具 @Tags 智能体 @Accept json @Produce json @Success 200 {object} map[string]interface{} "工具目录" @Security Bearer @Security ApiKeyAuth @Router /agents/tools [get]

func (*CustomAgentHandler) GetAgentTypePresets

func (h *CustomAgentHandler) GetAgentTypePresets(c *gin.Context)

GetAgentTypePresets godoc @Summary 获取智能体类型预设列表 @Description 返回所有 smart-reasoning 下可用的智能体类型预设(RAG/Wiki/Hybrid/Custom),用于编辑器自动填充系统提示词、工具和 KB 兼容性 @Tags 智能体 @Accept json @Produce json @Success 200 {object} map[string]interface{} "预设列表" @Security Bearer @Security ApiKeyAuth @Router /agents/type-presets [get]

func (*CustomAgentHandler) GetPlaceholders

func (h *CustomAgentHandler) GetPlaceholders(c *gin.Context)

GetPlaceholders godoc @Summary 获取占位符定义 @Description 获取所有可用的提示词占位符定义,按字段类型分组 @Tags 智能体 @Accept json @Produce json @Success 200 {object} map[string]interface{} "占位符定义" @Security Bearer @Security ApiKeyAuth @Router /agents/placeholders [get]

func (*CustomAgentHandler) GetSuggestedQuestions

func (h *CustomAgentHandler) GetSuggestedQuestions(c *gin.Context)

GetSuggestedQuestions godoc @Summary 获取推荐问题 @Description 基于智能体关联的知识库,返回推荐问题供用户快捷提问 @Tags 智能体 @Accept json @Produce json @Param id path string true "智能体ID" @Param knowledge_base_ids query string false "知识库ID列表(逗号分隔),覆盖智能体默认配置" @Param knowledge_ids query string false "知识ID列表(逗号分隔),限定到具体文档" @Param tag_scopes query string false "带知识库归属的标签范围(JSON)" @Param limit query int false "返回数量上限(未传时使用智能体配置的开场问题数量,最大30)" @Success 200 {object} map[string]interface{} "推荐问题列表" @Failure 400 {object} errors.AppError "请求参数错误" @Failure 404 {object} errors.AppError "智能体不存在" @Security Bearer @Security ApiKeyAuth @Router /agents/{id}/suggested-questions [get]

func (*CustomAgentHandler) ListAgents

func (h *CustomAgentHandler) ListAgents(c *gin.Context)

ListAgents godoc @Summary 获取智能体列表 @Description 获取当前空间的所有智能体(包括内置智能体) @Tags 智能体 @Accept json @Produce json @Success 200 {object} map[string]interface{} "智能体列表" @Failure 500 {object} errors.AppError "服务器错误" @Security Bearer @Security ApiKeyAuth @Router /agents [get]

func (*CustomAgentHandler) UpdateAgent

func (h *CustomAgentHandler) UpdateAgent(c *gin.Context)

UpdateAgent godoc @Summary 更新智能体 @Description 更新智能体的名称、描述和配置 @Tags 智能体 @Accept json @Produce json @Param id path string true "智能体ID" @Param request body UpdateAgentRequest true "更新请求" @Success 200 {object} map[string]interface{} "更新后的智能体" @Failure 400 {object} errors.AppError "请求参数错误" @Failure 403 {object} errors.AppError "无法修改内置智能体" @Security Bearer @Security ApiKeyAuth @Router /agents/{id} [put]

type DataSourceCredentialsHandler

type DataSourceCredentialsHandler struct {
	// contains filtered or unexported fields
}

DataSourceCredentialsHandler handles credentials for data source connectors via the dedicated /credentials subresource.

Unlike the other three resources (MCP / Model / WebSearch), DataSource credentials are a per-connector atomic map — there's no individual-field PUT or DELETE because half-configured connector auth doesn't work. So we expose a single logical field "credentials": GET returns whether anything is stored, PUT replaces the whole map, DELETE wipes it.

func (*DataSourceCredentialsHandler) DeleteField

func (h *DataSourceCredentialsHandler) DeleteField(c *gin.Context)

func (*DataSourceCredentialsHandler) Put

type DataSourceHandler

type DataSourceHandler struct {
	// contains filtered or unexported fields
}

DataSourceHandler handles HTTP requests for data source management

func NewDataSourceHandler

func NewDataSourceHandler(
	service interfaces.DataSourceService,
	kbService interfaces.KnowledgeBaseService,
) *DataSourceHandler

NewDataSourceHandler creates a new data source handler

func (*DataSourceHandler) CreateDataSource

func (h *DataSourceHandler) CreateDataSource(c *gin.Context)

CreateDataSource godoc @Summary Create a new data source @Description Create a new data source configuration for a knowledge base @Tags DataSource @Accept json @Produce json @Param request body types.DataSource true "Data source configuration" @Success 201 {object} types.DataSource @Failure 400 {object} map[string]string @Router /datasource [post]

func (*DataSourceHandler) DeleteDataSource

func (h *DataSourceHandler) DeleteDataSource(c *gin.Context)

DeleteDataSource godoc @Summary Delete a data source @Description Delete a data source (soft delete) @Tags DataSource @Param id path string true "Data source ID" @Success 204 @Failure 404 {object} map[string]string @Router /datasource/{id} [delete]

func (*DataSourceHandler) GetAvailableConnectors

func (h *DataSourceHandler) GetAvailableConnectors(c *gin.Context)

GetAvailableConnectors godoc @Summary Get available connectors @Description Get list of available data source connectors @Tags DataSource @Produce json @Success 200 {object} []datasource.ConnectorMetadata @Router /datasource/types [get]

func (*DataSourceHandler) GetDataSource

func (h *DataSourceHandler) GetDataSource(c *gin.Context)

GetDataSource godoc @Summary Get a data source by ID @Description Retrieve a data source configuration by ID @Tags DataSource @Produce json @Param id path string true "Data source ID" @Success 200 {object} types.DataSource @Failure 404 {object} map[string]string @Router /datasource/{id} [get]

func (*DataSourceHandler) GetSyncLog

func (h *DataSourceHandler) GetSyncLog(c *gin.Context)

GetSyncLog godoc @Summary Get specific sync log @Description Retrieve a specific sync log entry @Tags DataSource @Produce json @Param log_id path string true "Sync log ID" @Success 200 {object} types.SyncLog @Failure 404 {object} map[string]string @Router /datasource/logs/{log_id} [get]

func (*DataSourceHandler) GetSyncLogs

func (h *DataSourceHandler) GetSyncLogs(c *gin.Context)

GetSyncLogs godoc @Summary Get sync logs @Description Retrieve sync history for a data source @Tags DataSource @Produce json @Param id path string true "Data source ID" @Param limit query int false "Limit (default: 10)" @Param offset query int false "Offset (default: 0)" @Success 200 {object} []types.SyncLog @Failure 400 {object} map[string]string @Router /datasource/{id}/logs [get]

func (*DataSourceHandler) ListAvailableResources

func (h *DataSourceHandler) ListAvailableResources(c *gin.Context)

@Summary List available resources in data source @Description List resources available for sync in the external system. Pass parent_id to lazily load the direct children of a resource (used for large hierarchical sources such as Feishu wiki). @Tags DataSource @Produce json @Param id path string true "Data source ID" @Param parent_id query string false "Parent resource ExternalID; empty lists the top level" @Success 200 {object} []types.Resource @Failure 400 {object} map[string]string @Router /datasource/{id}/resources [get]

func (*DataSourceHandler) ListDataSources

func (h *DataSourceHandler) ListDataSources(c *gin.Context)

ListDataSources godoc @Summary List data sources for a knowledge base @Description List all data sources for a specific knowledge base @Tags DataSource @Produce json @Param kb_id query string true "Knowledge base ID" @Success 200 {object} []types.DataSource @Failure 400 {object} map[string]string @Router /datasource [get]

func (*DataSourceHandler) ManualSync

func (h *DataSourceHandler) ManualSync(c *gin.Context)

ManualSync godoc @Summary Trigger immediate sync @Description Trigger an immediate sync for a data source @Tags DataSource @Param id path string true "Data source ID" @Success 200 {object} types.SyncLog @Failure 400 {object} map[string]string @Router /datasource/{id}/sync [post]

func (*DataSourceHandler) PauseDataSource

func (h *DataSourceHandler) PauseDataSource(c *gin.Context)

PauseDataSource godoc @Summary Pause data source @Description Pause a data source's scheduled syncs @Tags DataSource @Param id path string true "Data source ID" @Success 200 {object} map[string]string @Failure 400 {object} map[string]string @Router /datasource/{id}/pause [post]

func (*DataSourceHandler) ResolveResourceAncestors

func (h *DataSourceHandler) ResolveResourceAncestors(c *gin.Context)

@Summary Resolve resource ancestors @Description Resolve the ancestor ExternalIDs that must be expanded to reveal the given (possibly deeply nested) resources in a lazily-loaded picker. Used to restore an existing selection when editing a data source. @Tags DataSource @Accept json @Produce json @Param id path string true "Data source ID" @Param request body resolveAncestorsRequest true "Resource IDs to resolve" @Success 200 {object} map[string][]string @Failure 400 {object} map[string]string @Router /datasource/{id}/resource-ancestors [post]

func (*DataSourceHandler) ResumeDataSource

func (h *DataSourceHandler) ResumeDataSource(c *gin.Context)

ResumeDataSource godoc @Summary Resume data source @Description Resume a paused data source @Tags DataSource @Param id path string true "Data source ID" @Success 200 {object} map[string]string @Failure 400 {object} map[string]string @Router /datasource/{id}/resume [post]

func (*DataSourceHandler) UpdateDataSource

func (h *DataSourceHandler) UpdateDataSource(c *gin.Context)

UpdateDataSource godoc @Summary Update a data source @Description Update an existing data source configuration @Tags DataSource @Accept json @Produce json @Param id path string true "Data source ID" @Param request body types.DataSource true "Updated configuration" @Success 200 {object} types.DataSource @Failure 400 {object} map[string]string @Router /datasource/{id} [put]

func (*DataSourceHandler) ValidateConnection

func (h *DataSourceHandler) ValidateConnection(c *gin.Context)

ValidateConnection godoc @Summary Test data source connection @Description Validate the connection to an external data source @Tags DataSource @Param id path string true "Data source ID" @Success 200 {object} map[string]string @Failure 400 {object} map[string]string @Router /datasource/{id}/validate [post]

func (*DataSourceHandler) ValidateCredentials

func (h *DataSourceHandler) ValidateCredentials(c *gin.Context)

ValidateCredentials godoc @Summary Test connection with raw credentials (no persistence) @Description Validate connectivity to an external data source using type + credentials

without creating or updating any database records.
Used by the frontend "Test Connection" button during data source creation.

@Tags DataSource @Accept json @Produce json @Param request body object true "type and credentials" @Success 200 {object} map[string]string @Failure 400 {object} map[string]string @Router /datasource/validate-credentials [post]

type DeleteTagRequest

type DeleteTagRequest struct {
	ExcludeIDs []int64 `json:"exclude_ids"` // Chunk seq_ids to exclude from deletion
}

DeleteTagRequest represents the request body for deleting a tag

type DeploymentCapabilitiesData

type DeploymentCapabilitiesData struct {
	Edition      string                          `json:"edition"`
	Capabilities map[string]DeploymentCapability `json:"capabilities"`
}

DeploymentCapabilitiesData is returned by GET /system/capabilities.

func BuildDeploymentCapabilities

func BuildDeploymentCapabilities(
	edition string,
	available DeploymentFeatureAvailability,
) DeploymentCapabilitiesData

BuildDeploymentCapabilities derives the deployment capability snapshot.

type DeploymentCapability

type DeploymentCapability struct {
	Supported bool   `json:"supported"`
	Reason    string `json:"reason,omitempty"`
}

DeploymentCapability describes whether a deployment exposes a feature route.

type DeploymentFeatureAvailability

type DeploymentFeatureAvailability struct {
	Organizations bool
	Agents        bool
	IM            bool
	Embed         bool
	API           bool
	MCPServer     bool
	MCP           bool
	WebSearch     bool
	VectorStore   bool
	Storage       bool
	Sandbox       bool
	SandboxDocker bool
	SandboxHost   bool
	SandboxRemote bool
}

DeploymentFeatureAvailability mirrors injected backend handlers/services.

type DownloadTask

type DownloadTask struct {
	ID        string     `json:"id"`
	ModelName string     `json:"modelName"`
	Status    string     `json:"status"` // pending, downloading, completed, failed
	Progress  float64    `json:"progress"`
	Message   string     `json:"message"`
	StartTime time.Time  `json:"startTime"`
	EndTime   *time.Time `json:"endTime,omitempty"`
}

DownloadTask 下载任务信息

type DuplicateKnowledgeBaseResponse

type DuplicateKnowledgeBaseResponse struct {
	SourceID      string      `json:"source_id"`
	TargetID      string      `json:"target_id"`
	Message       string      `json:"message"`
	KnowledgeBase interface{} `json:"knowledge_base"`
}

type EmbedChannelHandler

type EmbedChannelHandler struct {
	// contains filtered or unexported fields
}

EmbedChannelHandler manages web embed channel CRUD and public embed endpoints.

func NewEmbedChannelHandler

func NewEmbedChannelHandler(
	embedSvc interfaces.EmbedChannelService,
	sessionService interfaces.SessionService,
	sessionHandler *session.Handler,
	messageHandler *MessageHandler,
	suggestionHandler *MessageSuggestionHandler,
	mcpOAuthHandler *MCPOAuthHandler,
	mcpServiceHandler *MCPServiceHandler,
	redisClient *redis.Client,
) *EmbedChannelHandler

func (*EmbedChannelHandler) CreateEmbedChannel

func (h *EmbedChannelHandler) CreateEmbedChannel(c *gin.Context)

func (*EmbedChannelHandler) CreateEmbedSession

func (h *EmbedChannelHandler) CreateEmbedSession(c *gin.Context)

func (*EmbedChannelHandler) DeleteEmbedChannel

func (h *EmbedChannelHandler) DeleteEmbedChannel(c *gin.Context)

func (*EmbedChannelHandler) EmbedAgentChat

func (h *EmbedChannelHandler) EmbedAgentChat(c *gin.Context)

func (*EmbedChannelHandler) EmbedCancelMCPOAuth

func (h *EmbedChannelHandler) EmbedCancelMCPOAuth(c *gin.Context)

func (*EmbedChannelHandler) EmbedEnsureMessageSuggestions

func (h *EmbedChannelHandler) EmbedEnsureMessageSuggestions(c *gin.Context)

func (*EmbedChannelHandler) EmbedGetMessageSuggestions

func (h *EmbedChannelHandler) EmbedGetMessageSuggestions(c *gin.Context)

func (*EmbedChannelHandler) EmbedKnowledgeChat

func (h *EmbedChannelHandler) EmbedKnowledgeChat(c *gin.Context)

func (*EmbedChannelHandler) EmbedLoadMessages

func (h *EmbedChannelHandler) EmbedLoadMessages(c *gin.Context)

func (*EmbedChannelHandler) EmbedMCPOAuthAuthorizeURL

func (h *EmbedChannelHandler) EmbedMCPOAuthAuthorizeURL(c *gin.Context)

func (*EmbedChannelHandler) EmbedMCPOAuthStatus

func (h *EmbedChannelHandler) EmbedMCPOAuthStatus(c *gin.Context)

func (*EmbedChannelHandler) EmbedRecordSuggestionEvent

func (h *EmbedChannelHandler) EmbedRecordSuggestionEvent(c *gin.Context)

func (*EmbedChannelHandler) EmbedRelayWebhookEvent

func (h *EmbedChannelHandler) EmbedRelayWebhookEvent(c *gin.Context)

EmbedRelayWebhookEvent forwards a visitor chat event to the channel webhook URL.

func (*EmbedChannelHandler) EmbedResolveMCPOAuth

func (h *EmbedChannelHandler) EmbedResolveMCPOAuth(c *gin.Context)

func (*EmbedChannelHandler) EmbedResolveToolApproval

func (h *EmbedChannelHandler) EmbedResolveToolApproval(c *gin.Context)

func (*EmbedChannelHandler) EmbedStopSession

func (h *EmbedChannelHandler) EmbedStopSession(c *gin.Context)

func (*EmbedChannelHandler) ExchangeEmbedSession

func (h *EmbedChannelHandler) ExchangeEmbedSession(c *gin.Context)

func (*EmbedChannelHandler) GetEmbedChannel

func (h *EmbedChannelHandler) GetEmbedChannel(c *gin.Context)

GetEmbedChannel returns a single embed channel for management, including the publish token so admins can copy deploy snippets at any time.

func (*EmbedChannelHandler) GetEmbedChannelStats

func (h *EmbedChannelHandler) GetEmbedChannelStats(c *gin.Context)

GetEmbedChannelStats returns lightweight usage stats for an embed channel.

func (*EmbedChannelHandler) GetEmbedChunk

func (h *EmbedChannelHandler) GetEmbedChunk(c *gin.Context)

func (*EmbedChannelHandler) GetEmbedConfig

func (h *EmbedChannelHandler) GetEmbedConfig(c *gin.Context)

func (*EmbedChannelHandler) GetEmbedSuggestedQuestions

func (h *EmbedChannelHandler) GetEmbedSuggestedQuestions(c *gin.Context)

func (*EmbedChannelHandler) IssuePreviewSession

func (h *EmbedChannelHandler) IssuePreviewSession(c *gin.Context)

func (*EmbedChannelHandler) ListAllEmbedChannels

func (h *EmbedChannelHandler) ListAllEmbedChannels(c *gin.Context)

ListAllEmbedChannels lists every embed channel in the current tenant, across agents, for sidebar session grouping. Publish tokens are never included.

func (*EmbedChannelHandler) ListEmbedChannels

func (h *EmbedChannelHandler) ListEmbedChannels(c *gin.Context)

func (*EmbedChannelHandler) RotateEmbedToken

func (h *EmbedChannelHandler) RotateEmbedToken(c *gin.Context)

func (*EmbedChannelHandler) UpdateEmbedChannel

func (h *EmbedChannelHandler) UpdateEmbedChannel(c *gin.Context)

type EnsureMessageSuggestionsRequest

type EnsureMessageSuggestionsRequest struct {
	Regenerate bool `json:"regenerate"`
}

type EvaluationHandler

type EvaluationHandler struct {
	// contains filtered or unexported fields
}

EvaluationHandler handles evaluation related HTTP requests

func NewEvaluationHandler

func NewEvaluationHandler(evaluationService interfaces.EvaluationService) *EvaluationHandler

NewEvaluationHandler creates a new EvaluationHandler instance

func (*EvaluationHandler) Evaluation

func (e *EvaluationHandler) Evaluation(c *gin.Context)

Evaluation godoc @Summary 执行评估 @Description 对知识库进行评估测试 @Tags 评估 @Accept json @Produce json @Param request body EvaluationRequest true "评估请求参数" @Success 200 {object} map[string]interface{} "评估任务" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /evaluation/ [post]

func (*EvaluationHandler) GetEvaluationResult

func (e *EvaluationHandler) GetEvaluationResult(c *gin.Context)

GetEvaluationResult godoc @Summary 获取评估结果 @Description 根据任务ID获取评估结果 @Tags 评估 @Accept json @Produce json @Param task_id query string true "评估任务ID" @Success 200 {object} map[string]interface{} "评估结果" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /evaluation/ [get]

type EvaluationRequest

type EvaluationRequest struct {
	DatasetID       string `json:"dataset_id"`        // ID of dataset to evaluate
	KnowledgeBaseID string `json:"knowledge_base_id"` // ID of knowledge base to use
	ChatModelID     string `json:"chat_id"`           // ID of chat model to use
	RerankModelID   string `json:"rerank_id"`         // ID of rerank model to use
}

EvaluationRequest contains parameters for evaluation request

type FAQHandler

type FAQHandler struct {
	// contains filtered or unexported fields
}

FAQHandler handles FAQ knowledge base operations.

All KB-access checks (own / org-shared / via shared agent) are now performed by the route-level g.KBAccessRead / g.KBAccessWrite guards in router.go — the guard rewrites c.Request.Context() to carry the effective tenant ID for the duration of the handler, so the handler reads tenant from context the way it always did.

func NewFAQHandler

func NewFAQHandler(
	knowledgeService interfaces.KnowledgeService,
	kbService interfaces.KnowledgeBaseService,
) *FAQHandler

NewFAQHandler creates a new FAQ handler.

func (*FAQHandler) AddSimilarQuestions

func (h *FAQHandler) AddSimilarQuestions(c *gin.Context)

AddSimilarQuestions godoc @Summary 添加相似问 @Description 向指定的FAQ条目添加相似问题 @Tags FAQ管理 @Accept json @Produce json @Param id path string true "知识库ID" @Param entry_id path int true "FAQ条目ID(seq_id)" @Param request body addSimilarQuestionsRequest true "相似问列表" @Success 200 {object} map[string]interface{} "更新后的FAQ条目" @Failure 400 {object} errors.AppError "请求参数错误" @Failure 404 {object} errors.AppError "条目不存在" @Security Bearer @Security ApiKeyAuth @Router /knowledge-bases/{id}/faq/entries/{entry_id}/similar-questions [post]

func (*FAQHandler) CreateEntry

func (h *FAQHandler) CreateEntry(c *gin.Context)

CreateEntry godoc @Summary 创建单个FAQ条目 @Description 同步创建单个FAQ条目 @Tags FAQ管理 @Accept json @Produce json @Param id path string true "知识库ID" @Param request body types.FAQEntryPayload true "FAQ条目" @Success 200 {object} map[string]interface{} "创建的FAQ条目" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /knowledge-bases/{id}/faq/entry [post]

func (*FAQHandler) DeleteEntries

func (h *FAQHandler) DeleteEntries(c *gin.Context)

DeleteEntries godoc @Summary 批量删除FAQ条目 @Description 批量删除指定的FAQ条目 @Tags FAQ管理 @Accept json @Produce json @Param id path string true "知识库ID" @Param request body object{ids=[]int} true "要删除的FAQ ID列表(seq_id)" @Success 200 {object} map[string]interface{} "删除成功" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /knowledge-bases/{id}/faq/entries [delete]

func (*FAQHandler) ExportEntries

func (h *FAQHandler) ExportEntries(c *gin.Context)

ExportEntries godoc @Summary 导出FAQ条目 @Description 将所有FAQ条目导出为 CSV(默认)或 JSON。?format=json 返回与 FAQEntryPayload 结构兼容的数组。 @Tags FAQ管理 @Accept json @Produce text/csv @Produce application/json @Param id path string true "知识库ID" @Param format query string false "导出格式:csv(默认)或 json" @Success 200 {file} file "导出文件" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /knowledge-bases/{id}/faq/entries/export [get]

func (*FAQHandler) GetEntry

func (h *FAQHandler) GetEntry(c *gin.Context)

GetEntry godoc @Summary 获取FAQ条目详情 @Description 根据ID获取单个FAQ条目的详情 @Tags FAQ管理 @Accept json @Produce json @Param id path string true "知识库ID" @Param entry_id path int true "FAQ条目ID(seq_id)" @Success 200 {object} map[string]interface{} "FAQ条目详情" @Failure 400 {object} errors.AppError "请求参数错误" @Failure 404 {object} errors.AppError "条目不存在" @Security Bearer @Security ApiKeyAuth @Router /knowledge-bases/{id}/faq/entries/{entry_id} [get]

func (*FAQHandler) GetImportProgress

func (h *FAQHandler) GetImportProgress(c *gin.Context)

GetImportProgress godoc @Summary 获取FAQ导入进度 @Description 获取FAQ导入任务的进度 @Tags FAQ管理 @Accept json @Produce json @Param task_id path string true "任务ID" @Success 200 {object} map[string]interface{} "导入进度" @Failure 404 {object} errors.AppError "任务不存在" @Security Bearer @Security ApiKeyAuth @Router /faq/import/progress/{task_id} [get]

func (*FAQHandler) ListEntries

func (h *FAQHandler) ListEntries(c *gin.Context)

ListEntries godoc @Summary 获取FAQ条目列表 @Description 获取知识库下的FAQ条目列表,支持分页和筛选 @Tags FAQ管理 @Accept json @Produce json @Param id path string true "知识库ID" @Param page query int false "页码" @Param page_size query int false "每页数量" @Param tag_id query int false "标签ID筛选(seq_id),兼容旧版单标签" @Param tag_ids query string false "标签UUID筛选,逗号分隔(OR语义)" @Param keyword query string false "关键词搜索" @Param search_field query string false "搜索字段: standard_question(标准问题), similar_questions(相似问法), answers(答案), 默认搜索全部" @Param sort_order query string false "排序方式: asc(按更新时间正序), 默认按更新时间倒序" @Param is_enabled query bool false "启用状态筛选;不传时返回全部" @Success 200 {object} map[string]interface{} "FAQ列表" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /knowledge-bases/{id}/faq/entries [get]

func (*FAQHandler) SearchFAQ

func (h *FAQHandler) SearchFAQ(c *gin.Context)

SearchFAQ godoc @Summary 搜索FAQ @Description 使用混合搜索在FAQ中搜索,支持两级优先级标签召回:first_priority_tag_ids优先级最高,second_priority_tag_ids次之 @Tags FAQ管理 @Accept json @Produce json @Param id path string true "知识库ID" @Param request body types.FAQSearchRequest true "搜索请求" @Success 200 {object} map[string]interface{} "搜索结果" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /knowledge-bases/{id}/faq/search [post]

func (*FAQHandler) UpdateEntry

func (h *FAQHandler) UpdateEntry(c *gin.Context)

UpdateEntry godoc @Summary 更新FAQ条目 @Description 更新指定的FAQ条目 @Tags FAQ管理 @Accept json @Produce json @Param id path string true "知识库ID" @Param entry_id path int true "FAQ条目ID(seq_id)" @Param request body types.FAQEntryPayload true "FAQ条目" @Success 200 {object} map[string]interface{} "更新成功" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /knowledge-bases/{id}/faq/entries/{entry_id} [put]

func (*FAQHandler) UpdateEntryFieldsBatch

func (h *FAQHandler) UpdateEntryFieldsBatch(c *gin.Context)

UpdateEntryFieldsBatch godoc @Summary 批量更新FAQ字段 @Description 批量更新FAQ条目的多个字段(is_enabled, is_recommended, tag_id) @Tags FAQ管理 @Accept json @Produce json @Param id path string true "知识库ID" @Param request body types.FAQEntryFieldsBatchUpdate true "字段更新请求" @Success 200 {object} map[string]interface{} "更新成功" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /knowledge-bases/{id}/faq/entries/fields [put]

func (*FAQHandler) UpdateEntryTagBatch

func (h *FAQHandler) UpdateEntryTagBatch(c *gin.Context)

UpdateEntryTagBatch godoc @Summary 批量更新FAQ标签 @Description 批量更新FAQ条目的标签 @Tags FAQ管理 @Accept json @Produce json @Param id path string true "知识库ID" @Param request body object true "标签更新请求" @Success 200 {object} map[string]interface{} "更新成功" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /knowledge-bases/{id}/faq/entries/tags [put]

func (*FAQHandler) UpdateLastImportResultDisplayStatus

func (h *FAQHandler) UpdateLastImportResultDisplayStatus(c *gin.Context)

UpdateLastImportResultDisplayStatus godoc @Summary 更新FAQ最后一次导入结果显示状态 @Description 更新FAQ知识库导入结果统计卡片的显示或隐藏状态 @Tags FAQ管理 @Accept json @Produce json @Param id path string true "知识库ID" @Param request body updateLastFAQImportResultDisplayStatusRequest true "状态更新请求" @Success 200 {object} map[string]interface{} "更新成功" @Failure 400 {object} errors.AppError "请求参数错误" @Failure 404 {object} errors.AppError "知识库不存在或无导入记录" @Security Bearer @Security ApiKeyAuth @Router /knowledge-bases/{id}/faq/import/last-result/display [put]

func (*FAQHandler) UpsertEntries

func (h *FAQHandler) UpsertEntries(c *gin.Context)

UpsertEntries godoc @Summary 批量更新/插入FAQ条目 @Description 异步批量更新或插入FAQ条目。支持 dry_run 模式(设置 dry_run=true),异步验证不实际导入。 @Description dry_run 模式是异步操作,返回 task_id,通过 /faq/import/progress/{task_id} 查询进度和结果。 @Description 验证内容包括:1) 条目基本格式 2) 重复问题(批次内和知识库已有) 3) 内容安全检查。 @Tags FAQ管理 @Accept json @Produce json @Param id path string true "知识库ID" @Param request body types.FAQBatchUpsertPayload true "批量操作请求" @Success 200 {object} map[string]interface{} "任务ID" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /knowledge-bases/{id}/faq/entries [post]

type FabriTagRequest

type FabriTagRequest struct{}

FabriTagRequest is a request for generating tags

type FabriTagResponse

type FabriTagResponse struct {
	Tags []string `json:"tags"`
}

FabriTagResponse is a response for generating tags

type FabriTextRequest

type FabriTextRequest struct {
	Tags    []string `json:"tags"`
	ModelID string   `json:"model_id" binding:"required"`
}

FabriTextRequest is a request for generating example text

type FabriTextResponse

type FabriTextResponse struct {
	Text string `json:"text"`
}

FabriTextResponse is a response for generating example text

type GetEvaluationRequest

type GetEvaluationRequest struct {
	TaskID string `form:"task_id" binding:"required"` // ID of evaluation task
}

GetEvaluationRequest contains parameters for getting evaluation result

type GetKnowledgeBatchRequest

type GetKnowledgeBatchRequest struct {
	IDs                 []string `form:"ids" binding:"required"` // List of knowledge IDs
	KBID                string   `form:"kb_id"`                  // Optional: scope to this KB (validates access and uses effective tenant for shared KB)
	AgentID             string   `form:"agent_id"`               // Optional: when using a shared agent, use agent's tenant for retrieval (validates shared agent access)
	AgentSourceTenantID uint64   `form:"agent_source_tenant_id"` // Optional source selector, verified against the share relation
}

GetKnowledgeBatchRequest defines parameters for batch knowledge retrieval

type GetStorageEngineStatusResponse

type GetStorageEngineStatusResponse struct {
	Engines           []StorageEngineStatusItem `json:"engines"`
	AllowedProviders  []string                  `json:"allowed_providers"`
	MinioEnvAvailable bool                      `json:"minio_env_available"`
}

GetStorageEngineStatusResponse is the response for GET /system/storage-engine-status.

type GetSystemInfoResponse

type GetSystemInfoResponse struct {
	Version             string `json:"version"`
	Edition             string `json:"edition"`
	CommitID            string `json:"commit_id,omitempty"`
	BuildTime           string `json:"build_time,omitempty"`
	GoVersion           string `json:"go_version,omitempty"`
	KeywordIndexEngine  string `json:"keyword_index_engine,omitempty"`
	VectorStoreEngine   string `json:"vector_store_engine,omitempty"`
	GraphDatabaseEngine string `json:"graph_database_engine,omitempty"`
	MinioEnabled        bool   `json:"minio_enabled,omitempty"`
	DBVersion           string `json:"db_version,omitempty"`
	// DBMigrationError carries the human-readable error message recorded when
	// the most recent startup migration attempt failed. Empty when migrations
	// succeeded; non-empty values let the frontend surface a troubleshooting
	// banner instead of silently hiding the DB version row (see issue #1319).
	DBMigrationError string `json:"db_migration_error,omitempty"`
	// StartedAt is the server process boot time (RFC3339, UTC).
	StartedAt string `json:"started_at,omitempty"`
	// UptimeSeconds is seconds elapsed since process start.
	UptimeSeconds int64 `json:"uptime_seconds,omitempty"`
}

GetSystemInfoResponse defines the response structure for system info

type IMHandler

type IMHandler struct {
	// contains filtered or unexported fields
}

IMHandler handles IM platform callback requests and channel CRUD.

func NewIMHandler

func NewIMHandler(imService *im.Service) *IMHandler

NewIMHandler creates a new IM handler.

func (*IMHandler) CreateIMChannel

func (h *IMHandler) CreateIMChannel(c *gin.Context)

CreateIMChannel creates a new IM channel for an agent.

func (*IMHandler) DeleteIMChannel

func (h *IMHandler) DeleteIMChannel(c *gin.Context)

DeleteIMChannel deletes an IM channel.

DeleteIMChannel godoc @Summary 删除 IM 渠道 @Description 删除指定 IM 渠道 @Tags IM 渠道 @Produce json @Param id path string true "渠道 ID" @Success 200 {object} map[string]interface{} "success: true" @Failure 400 {object} map[string]interface{} "请求参数错误" @Failure 404 {object} map[string]interface{} "渠道不存在" @Security Bearer @Security ApiKeyAuth @Router /im-channels/{id} [delete]

func (*IMHandler) IMCallback

func (h *IMHandler) IMCallback(c *gin.Context)

IMCallback handles IM platform callback requests for a specific channel. Route: POST /api/v1/im/callback/:channel_id

IMCallback godoc @Summary IM 平台回调 @Description 接收各 IM 平台的事件回调;走平台自身签名校验,不使用 API Key @Tags IM 回调 @Accept json @Produce json @Param channel_id path string true "渠道 ID" @Success 200 {object} map[string]interface{} "处理结果" @Failure 400 {object} map[string]interface{} "请求参数错误" @Failure 401 {object} map[string]interface{} "签名校验失败" @Router /im/callback/{channel_id} [get] @Router /im/callback/{channel_id} [post]

func (*IMHandler) ListAllIMChannels

func (h *IMHandler) ListAllIMChannels(c *gin.Context)

ListAllIMChannels lists every IM channel in the current tenant, across agents, for the cross-agent overview page. Credentials are intentionally NOT included in the response.

func (*IMHandler) ListIMChannels

func (h *IMHandler) ListIMChannels(c *gin.Context)

ListIMChannels lists all IM channels for an agent.

func (*IMHandler) ToggleIMChannel

func (h *IMHandler) ToggleIMChannel(c *gin.Context)

ToggleIMChannel toggles the enabled state of an IM channel.

ToggleIMChannel godoc @Summary 启用/停用 IM 渠道 @Description 切换指定 IM 渠道的启用状态 @Tags IM 渠道 @Produce json @Param id path string true "渠道 ID" @Success 200 {object} map[string]interface{} "更新后的渠道" @Failure 400 {object} map[string]interface{} "请求参数错误" @Failure 404 {object} map[string]interface{} "渠道不存在" @Security Bearer @Security ApiKeyAuth @Router /im-channels/{id}/toggle [post]

func (*IMHandler) UpdateIMChannel

func (h *IMHandler) UpdateIMChannel(c *gin.Context)

UpdateIMChannel updates an IM channel.

UpdateIMChannel godoc @Summary 更新 IM 渠道 @Description 更新指定 IM 渠道的名称、模式、回复语言、知识库、凭证或启用状态 @Tags IM 渠道 @Accept json @Produce json @Param id path string true "渠道 ID" @Param request body map[string]interface{} true "更新字段(含 locale)" @Success 200 {object} map[string]interface{} "更新后的渠道" @Failure 400 {object} map[string]interface{} "请求参数错误" @Failure 404 {object} map[string]interface{} "渠道不存在" @Security Bearer @Security ApiKeyAuth @Router /im-channels/{id} [put]

func (*IMHandler) WeChatGetQRCode

func (h *IMHandler) WeChatGetQRCode(c *gin.Context)

WeChatGetQRCode generates a QR code for WeChat login. POST /api/v1/wechat/qrcode

WeChatGetQRCode godoc @Summary 获取微信扫码登录二维码 @Description 申请一个用于扫码登录绑定的微信二维码(无请求体) @Tags IM 渠道 @Produce json @Success 200 {object} map[string]interface{} "二维码信息(qrcode_url + qrcode 标识)" @Failure 500 {object} map[string]interface{} "二维码生成失败" @Security Bearer @Security ApiKeyAuth @Router /wechat/qrcode [post]

func (*IMHandler) WeChatPollQRCodeStatus

func (h *IMHandler) WeChatPollQRCodeStatus(c *gin.Context)

WeChatPollQRCodeStatus checks the scan status of a WeChat QR code. POST /api/v1/wechat/qrcode/status

WeChatPollQRCodeStatus godoc @Summary 轮询微信二维码状态 @Description 查询指定二维码是否已被扫描/确认/过期;confirmed 时返回凭证 @Tags IM 渠道 @Accept json @Produce json @Param request body map[string]interface{} true "{qrcode: string}" @Success 200 {object} map[string]interface{} "扫码状态" @Failure 400 {object} map[string]interface{} "请求参数错误" @Failure 500 {object} map[string]interface{} "服务器错误" @Security Bearer @Security ApiKeyAuth @Router /wechat/qrcode/status [post]

type InitializationHandler

type InitializationHandler struct {
	// contains filtered or unexported fields
}

InitializationHandler 初始化处理器

func NewInitializationHandler

func NewInitializationHandler(
	config *config.Config,
	tenantService interfaces.TenantService,
	modelService interfaces.ModelService,
	kbService interfaces.KnowledgeBaseService,
	kbRepository interfaces.KnowledgeBaseRepository,
	knowledgeService interfaces.KnowledgeService,
	ollamaService *ollama.OllamaService,
	documentReader interfaces.DocumentReader,
	pooler embedding.EmbedderPooler,
	storageResolver interfaces.StorageBackendResolver,
) *InitializationHandler

NewInitializationHandler 创建初始化处理器

func (*InitializationHandler) CheckASRModel

func (h *InitializationHandler) CheckASRModel(c *gin.Context)

CheckASRModel godoc @Summary 检查ASR模型 @Description 检查ASR(语音识别)模型连接是否正常,通过发送一段静默音频测试 /v1/audio/transcriptions 端点 @Tags 初始化 @Accept json @Produce json @Param request body handler.ModelTestRequest true "ASR检查请求" @Success 200 {object} map[string]interface{} "检查结果" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /initialization/asr/check [post]

func (*InitializationHandler) CheckOllamaModels

func (h *InitializationHandler) CheckOllamaModels(c *gin.Context)

CheckOllamaModels godoc @Summary 检查Ollama模型状态 @Description 检查指定的Ollama模型是否已安装 @Tags 初始化 @Accept json @Produce json @Param request body object{models=[]string} true "模型名称列表" @Success 200 {object} map[string]interface{} "模型状态" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /initialization/ollama/models/check [post]

func (*InitializationHandler) CheckOllamaStatus

func (h *InitializationHandler) CheckOllamaStatus(c *gin.Context)

CheckOllamaStatus godoc @Summary 检查Ollama服务状态 @Description 检查Ollama服务是否可用 @Tags 初始化 @Accept json @Produce json @Success 200 {object} map[string]interface{} "Ollama状态" @Router /initialization/ollama/status [get]

func (*InitializationHandler) CheckRemoteModel

func (h *InitializationHandler) CheckRemoteModel(c *gin.Context)

CheckRemoteModel godoc @Summary 检查远程模型 @Description 检查远程API模型连接是否正常 @Tags 初始化 @Accept json @Produce json @Param request body RemoteModelCheckRequest true "模型检查请求" @Success 200 {object} map[string]interface{} "检查结果" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /initialization/remote/check [post]

func (*InitializationHandler) CheckRerankModel

func (h *InitializationHandler) CheckRerankModel(c *gin.Context)

CheckRerankModel godoc @Summary 检查Rerank模型 @Description 检查Rerank模型连接和功能是否正常 @Tags 初始化 @Accept json @Produce json @Param request body handler.ModelTestRequest true "Rerank检查请求" @Success 200 {object} map[string]interface{} "检查结果" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /initialization/rerank/check [post]

func (*InitializationHandler) DownloadOllamaModel

func (h *InitializationHandler) DownloadOllamaModel(c *gin.Context)

DownloadOllamaModel godoc @Summary 下载Ollama模型 @Description 异步下载指定的Ollama模型 @Tags 初始化 @Accept json @Produce json @Param request body object{modelName=string} true "模型名称" @Success 200 {object} map[string]interface{} "下载任务信息" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /initialization/ollama/models/download [post]

func (*InitializationHandler) ExtractTextRelations

func (h *InitializationHandler) ExtractTextRelations(c *gin.Context)

ExtractTextRelations godoc @Summary 提取文本关系 @Description 从文本中提取实体和关系 @Tags 初始化 @Accept json @Produce json @Param request body TextRelationExtractionRequest true "提取请求" @Success 200 {object} map[string]interface{} "提取结果" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /initialization/extract/text-relation [post]

func (*InitializationHandler) FabriTag

func (h *InitializationHandler) FabriTag(c *gin.Context)

FabriTag godoc @Summary 生成随机标签 @Description 随机生成一组标签 @Tags 初始化 @Accept json @Produce json @Success 200 {object} map[string]interface{} "生成的标签" @Router /initialization/extract/fabri-tag [post]

func (*InitializationHandler) FabriText

func (h *InitializationHandler) FabriText(c *gin.Context)

FabriText godoc @Summary 生成示例文本 @Description 根据标签生成示例文本 @Tags 初始化 @Accept json @Produce json @Param request body FabriTextRequest true "生成请求" @Success 200 {object} map[string]interface{} "生成的文本" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /initialization/extract/fabri-text [post]

func (*InitializationHandler) GetCurrentConfigByKB

func (h *InitializationHandler) GetCurrentConfigByKB(c *gin.Context)

GetCurrentConfigByKB godoc @Summary 获取知识库配置 @Description 根据知识库ID获取当前配置信息 @Tags 初始化 @Accept json @Produce json @Param kbId path string true "知识库ID" @Success 200 {object} map[string]interface{} "配置信息" @Failure 404 {object} errors.AppError "知识库不存在" @Security Bearer @Security ApiKeyAuth @Router /initialization/config/{kbId} [get]

func (*InitializationHandler) GetDownloadProgress

func (h *InitializationHandler) GetDownloadProgress(c *gin.Context)

GetDownloadProgress godoc @Summary 获取下载进度 @Description 获取Ollama模型下载任务的进度 @Tags 初始化 @Accept json @Produce json @Param taskId path string true "任务ID" @Success 200 {object} map[string]interface{} "下载进度" @Failure 404 {object} errors.AppError "任务不存在" @Security Bearer @Security ApiKeyAuth @Router /initialization/ollama/download/progress/{taskId} [get]

func (*InitializationHandler) InitializeByKB

func (h *InitializationHandler) InitializeByKB(c *gin.Context)

InitializeByKB godoc @Summary 初始化知识库配置 @Description 根据知识库ID执行完整配置更新 @Tags 初始化 @Accept json @Produce json @Param kbId path string true "知识库ID" @Param request body handler.InitializationRequest true "初始化请求" @Success 200 {object} map[string]interface{} "初始化成功" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /initialization/initialize/{kbId} [post]

func (*InitializationHandler) ListDownloadTasks

func (h *InitializationHandler) ListDownloadTasks(c *gin.Context)

ListDownloadTasks godoc @Summary 列出下载任务 @Description 列出所有Ollama模型下载任务 @Tags 初始化 @Accept json @Produce json @Success 200 {object} map[string]interface{} "任务列表" @Security Bearer @Security ApiKeyAuth @Router /initialization/ollama/download/tasks [get]

func (*InitializationHandler) ListOllamaModels

func (h *InitializationHandler) ListOllamaModels(c *gin.Context)

ListOllamaModels godoc @Summary 列出Ollama模型 @Description 列出已安装的Ollama模型 @Tags 初始化 @Accept json @Produce json @Success 200 {object} map[string]interface{} "模型列表" @Failure 500 {object} errors.AppError "服务器错误" @Security Bearer @Security ApiKeyAuth @Router /initialization/ollama/models [get]

func (*InitializationHandler) TestEmbeddingModel

func (h *InitializationHandler) TestEmbeddingModel(c *gin.Context)

TestEmbeddingModel godoc @Summary 测试Embedding模型 @Description 测试Embedding接口是否可用并返回向量维度 @Tags 初始化 @Accept json @Produce json @Param request body handler.ModelTestRequest true "Embedding测试请求" @Success 200 {object} map[string]interface{} "测试结果" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /initialization/embedding/test [post]

func (*InitializationHandler) TestMultimodalFunction

func (h *InitializationHandler) TestMultimodalFunction(c *gin.Context)

TestMultimodalFunction godoc @Summary 测试多模态功能 @Description 上传图片测试多模态处理功能 @Tags 初始化 @Accept multipart/form-data @Produce json @Param image formData file true "测试图片" @Param vlm_model formData string true "VLM模型名称" @Param vlm_base_url formData string true "VLM Base URL" @Param vlm_api_key formData string false "VLM API Key" @Param vlm_interface_type formData string false "VLM接口类型" @Param storage_type formData string true "存储类型(cos/minio)" @Success 200 {object} map[string]interface{} "测试结果" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /initialization/multimodal/test [post]

func (*InitializationHandler) UpdateKBConfig

func (h *InitializationHandler) UpdateKBConfig(c *gin.Context)

UpdateKBConfig godoc @Summary 更新知识库配置 @Description 根据知识库ID更新模型和分块配置 @Tags 初始化 @Accept json @Produce json @Param kbId path string true "知识库ID" @Param request body KBModelConfigRequest true "配置请求" @Success 200 {object} map[string]interface{} "更新成功" @Failure 400 {object} errors.AppError "请求参数错误" @Failure 404 {object} errors.AppError "知识库不存在" @Security Bearer @Security ApiKeyAuth @Router /initialization/config/{kbId} [put]

type InitializationRequest

type InitializationRequest struct {
	LLM struct {
		Source    string `json:"source" binding:"required"`
		ModelName string `json:"modelName" binding:"required"`
		BaseURL   string `json:"baseUrl"`
		APIKey    string `json:"apiKey"`
	} `json:"llm" binding:"required"`

	Embedding struct {
		Source    string `json:"source" binding:"required"`
		ModelName string `json:"modelName" binding:"required"`
		BaseURL   string `json:"baseUrl"`
		APIKey    string `json:"apiKey"`
		Dimension int    `json:"dimension"` // 添加embedding维度字段
	} `json:"embedding" binding:"required"`

	Rerank struct {
		Enabled   bool   `json:"enabled"`
		ModelName string `json:"modelName"`
		BaseURL   string `json:"baseUrl"`
		APIKey    string `json:"apiKey"`
	} `json:"rerank"`

	Multimodal struct {
		Enabled bool `json:"enabled"`
		VLM     *struct {
			ModelName     string `json:"modelName"`
			BaseURL       string `json:"baseUrl"`
			APIKey        string `json:"apiKey"`
			InterfaceType string `json:"interfaceType"` // "ollama" or "openai"
		} `json:"vlm,omitempty"`
		StorageType string `json:"storageType"`
		COS         *struct {
			SecretID   string `json:"secretId"`
			SecretKey  string `json:"secretKey"`
			Region     string `json:"region"`
			BucketName string `json:"bucketName"`
			AppID      string `json:"appId"`
			PathPrefix string `json:"pathPrefix"`
		} `json:"cos,omitempty"`
		Minio *struct {
			BucketName string `json:"bucketName"`
			PathPrefix string `json:"pathPrefix"`
		} `json:"minio,omitempty"`
	} `json:"multimodal"`

	DocumentSplitting struct {
		ChunkSize    int      `json:"chunkSize" binding:"required,min=100,max=10000"`
		ChunkOverlap int      `json:"chunkOverlap" binding:"min=0"`
		Separators   []string `json:"separators" binding:"required,min=1"`
	} `json:"documentSplitting" binding:"required"`

	NodeExtract struct {
		Enabled bool     `json:"enabled"`
		Text    string   `json:"text"`
		Tags    []string `json:"tags"`
		Nodes   []struct {
			Name       string   `json:"name"`
			Attributes []string `json:"attributes"`
		} `json:"nodes"`
		Relations []struct {
			Node1 string `json:"node1"`
			Node2 string `json:"node2"`
			Type  string `json:"type"`
		} `json:"relations"`
	} `json:"nodeExtract"`

	QuestionGeneration struct {
		Enabled       bool `json:"enabled"`
		QuestionCount int  `json:"questionCount"`
	} `json:"questionGeneration"`
}

InitializationRequest 初始化请求结构

type KBModelConfigRequest

type KBModelConfigRequest struct {
	LLMModelID       string           `json:"llmModelId"       binding:"required"`
	EmbeddingModelID string           `json:"embeddingModelId"` // optional when RAG indexing is disabled
	VLMConfig        *types.VLMConfig `json:"vlm_config"`
	ASRConfig        *types.ASRConfig `json:"asr_config"`

	// 文档分块配置
	DocumentSplitting struct {
		ChunkSize         int                      `json:"chunkSize"`
		ChunkOverlap      int                      `json:"chunkOverlap"`
		Separators        []string                 `json:"separators"`
		ParserEngineRules []types.ParserEngineRule `json:"parserEngineRules,omitempty"`
		EnableParentChild bool                     `json:"enableParentChild"`
		ParentChunkSize   int                      `json:"parentChunkSize,omitempty"`
		ChildChunkSize    int                      `json:"childChunkSize,omitempty"`
		// Strategy / TokenLimit / Languages use pointer types so the
		// handler can distinguish "field absent in payload" (no change)
		// from "field present with empty/zero value" (clear / disable).
		// Without that distinction, users could set strategy="auto" once
		// but never reset it back to legacy / unset.
		Strategy                  *string   `json:"strategy,omitempty"`
		TokenLimit                *int      `json:"tokenLimit,omitempty"`
		Languages                 *[]string `json:"languages,omitempty"`
		TableMetadataInstructions *string   `json:"tableMetadataInstructions,omitempty"`
	} `json:"documentSplitting"`

	// 多模态配置(仅模型相关;存储引擎在 storageProvider 中配置)
	Multimodal struct {
		Enabled bool `json:"enabled"`
	} `json:"multimodal"`

	// 存储引擎选择("local" | "minio" | "cos"),影响文档上传与文档内图片存储,参数从全局设置读取
	StorageProvider  string `json:"storageProvider"`
	StorageBackendID string `json:"storageBackendId"`

	// 知识图谱配置
	NodeExtract struct {
		Enabled            bool                  `json:"enabled"`
		Text               string                `json:"text"`
		Tags               []string              `json:"tags"`
		Nodes              []types.GraphNode     `json:"nodes"`
		Relations          []types.GraphRelation `json:"relations"`
		CustomInstructions string                `json:"customInstructions"`
	} `json:"nodeExtract"`

	// 问题生成配置
	QuestionGeneration struct {
		Enabled            bool   `json:"enabled"`
		QuestionCount      int    `json:"questionCount"`
		CustomInstructions string `json:"customInstructions"`
	} `json:"questionGeneration"`
}

KBModelConfigRequest 知识库模型配置请求(简化版,只传模型ID)

type KnowledgeBaseHandler

type KnowledgeBaseHandler struct {
	// contains filtered or unexported fields
}

KnowledgeBaseHandler defines the HTTP handler for knowledge base operations

func NewKnowledgeBaseHandler

func NewKnowledgeBaseHandler(
	cfg *config.Config,
	service interfaces.KnowledgeBaseService,
	knowledgeService interfaces.KnowledgeService,
	kbShareService interfaces.KBShareService,
	agentShareService interfaces.AgentShareService,
	asynqClient interfaces.TaskEnqueuer,
	vectorStoreService interfaces.VectorStoreService,
	userService interfaces.UserService,
	fileService interfaces.FileService,
	storageResolver interfaces.StorageBackendResolver,
	profileService interfaces.KnowledgeBaseProfileService,
) *KnowledgeBaseHandler

NewKnowledgeBaseHandler creates a new knowledge base handler instance

func (*KnowledgeBaseHandler) CopyKnowledgeBase

func (h *KnowledgeBaseHandler) CopyKnowledgeBase(c *gin.Context)

CopyKnowledgeBase godoc @Summary 复制知识库 @Description 将一个知识库的内容复制到另一个知识库(异步任务) @Tags 知识库 @Accept json @Produce json @Param request body CopyKnowledgeBaseRequest true "复制请求" @Success 200 {object} map[string]interface{} "任务ID" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /knowledge-bases/copy [post]

func (*KnowledgeBaseHandler) CreateKnowledgeBase

func (h *KnowledgeBaseHandler) CreateKnowledgeBase(c *gin.Context)

CreateKnowledgeBase godoc @Summary 创建知识库 @Description 创建新的知识库 @Tags 知识库 @Accept json @Produce json @Param request body types.KnowledgeBase true "知识库信息" @Success 201 {object} map[string]interface{} "创建的知识库" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /knowledge-bases [post]

func (*KnowledgeBaseHandler) DeleteKnowledgeBase

func (h *KnowledgeBaseHandler) DeleteKnowledgeBase(c *gin.Context)

DeleteKnowledgeBase godoc @Summary 删除知识库 @Description 删除指定的知识库及其所有内容 @Tags 知识库 @Accept json @Produce json @Param id path string true "知识库ID" @Success 200 {object} map[string]interface{} "删除成功" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /knowledge-bases/{id} [delete]

func (*KnowledgeBaseHandler) DuplicateKnowledgeBase

func (h *KnowledgeBaseHandler) DuplicateKnowledgeBase(c *gin.Context)

DuplicateKnowledgeBase godoc @Summary 创建知识库副本 @Description 创建一个只包含设置的新知识库副本,不复制知识、FAQ 内容、分块、索引、Wiki 页面、分享或置顶状态 @Tags 知识库 @Accept json @Produce json @Param id path string true "源知识库 ID" @Success 201 {object} map[string]interface{} "创建后的知识库副本" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Router /knowledge-bases/{id}/duplicate [post]

func (*KnowledgeBaseHandler) GenerateKnowledgeBaseProfile

func (h *KnowledgeBaseHandler) GenerateKnowledgeBaseProfile(c *gin.Context)

GenerateKnowledgeBaseProfile godoc @Summary 生成知识库描述 @Description 基于文档画像聚合,立即重新生成知识库的 AI 描述(不覆盖手写描述) @Tags 知识库 @Produce json @Param id path string true "知识库ID" @Success 200 {object} map[string]interface{} "生成的知识库画像" @Failure 400 {object} errors.AppError "知识库类型不支持或未配置模型" @Security Bearer @Security ApiKeyAuth @Router /knowledge-bases/{id}/profile/generate [post]

func (*KnowledgeBaseHandler) GetImageAttrsSchema

func (h *KnowledgeBaseHandler) GetImageAttrsSchema(c *gin.Context)

GetImageAttrsSchema returns the canonical image-attribute registry for this release. It is the single source of truth that drives the frontend attribute panel — both the attributes and their display text (label, description, the meaning of each value) — so adding an attribute later is a backend-only change (one registry row) and the UI follows automatically. Read-only; the registry is global, not per-KB, so it carries no KB id and only the Viewer role is required.

func (*KnowledgeBaseHandler) GetKBCloneProgress

func (h *KnowledgeBaseHandler) GetKBCloneProgress(c *gin.Context)

GetKBCloneProgress godoc @Summary 获取知识库复制进度 @Description 获取知识库复制任务的进度 @Tags 知识库 @Accept json @Produce json @Param task_id path string true "任务ID" @Success 200 {object} map[string]interface{} "进度信息" @Failure 404 {object} errors.AppError "任务不存在" @Security Bearer @Security ApiKeyAuth @Router /knowledge-bases/copy/progress/{task_id} [get]

func (*KnowledgeBaseHandler) GetKnowledgeBase

func (h *KnowledgeBaseHandler) GetKnowledgeBase(c *gin.Context)

GetKnowledgeBase godoc @Summary 获取知识库详情 @Description 根据ID获取知识库详情。当使用共享智能体时,可传 agent_id 以校验该智能体是否有权访问该知识库。 @Tags 知识库 @Accept json @Produce json @Param id path string true "知识库ID" @Param agent_id query string false "共享智能体 ID(用于校验智能体是否有权访问该知识库)" @Success 200 {object} map[string]interface{} "知识库详情" @Failure 400 {object} errors.AppError "请求参数错误" @Failure 404 {object} errors.AppError "知识库不存在" @Security Bearer @Security ApiKeyAuth @Router /knowledge-bases/{id} [get]

func (*KnowledgeBaseHandler) HybridSearch

func (h *KnowledgeBaseHandler) HybridSearch(c *gin.Context)

HybridSearch godoc @Summary 混合搜索 @Description 底层召回:向量+关键词混合检索,默认不 rerank(可用 rerank 字段开启);一般检索请用 /knowledge-search。推荐 POST,GET 带 JSON 体仅兼容旧客户端。 @Tags 知识库 @Accept json @Produce json @Param id path string true "知识库ID" @Param request body types.SearchParams true "搜索参数" @Param resource_urls query string false "文件引用形式,public 返回可加载直链" Enums(handle, public) default(handle) @Success 200 {object} map[string]interface{} "搜索结果" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /knowledge-bases/{id}/hybrid-search [post] @Router /knowledge-bases/{id}/hybrid-search [get]

func (*KnowledgeBaseHandler) KBCreatorLookup

func (h *KnowledgeBaseHandler) KBCreatorLookup(c *gin.Context) (string, error)

KBCreatorLookup resolves :id -> KnowledgeBase.CreatorID, scoped to the caller's tenant. Used by all per-KB mutating routes.

func (*KnowledgeBaseHandler) KBCreatorLookupFromKbIDParam

func (h *KnowledgeBaseHandler) KBCreatorLookupFromKbIDParam(c *gin.Context) (string, error)

KBCreatorLookupFromKbIDParam is the same lookup as KBCreatorLookup but reads `:kbId` instead of `:id`. Used by the /initialization routes (POST /initialization/initialize/:kbId, PUT /initialization/config/:kbId), which are KB-scoped mutating ops: changing a KB's embedding/parser/storage configuration is at least as sensitive as updating the KB itself, so it must follow the same "creator OR Admin+" matrix.

func (*KnowledgeBaseHandler) ListKnowledgeBases

func (h *KnowledgeBaseHandler) ListKnowledgeBases(c *gin.Context)

ListKnowledgeBases godoc @Summary 获取知识库列表 @Description 获取当前空间的所有知识库;或当传入 agent_id(共享智能体)时,校验权限后返回该智能体配置的知识库范围(用于 @ 提及) @Tags 知识库 @Accept json @Produce json @Param agent_id query string false "共享智能体 ID(传入时返回该智能体可用的知识库)" @Success 200 {object} map[string]interface{} "知识库列表" @Failure 500 {object} errors.AppError "服务器错误" @Security Bearer @Security ApiKeyAuth @Router /knowledge-bases [get]

func (*KnowledgeBaseHandler) ListMoveTargets

func (h *KnowledgeBaseHandler) ListMoveTargets(c *gin.Context)

ListMoveTargets returns knowledge bases eligible as move targets for the given source KB. Filters: same Type, same EmbeddingModelID, different ID, not temporary.

ListMoveTargets godoc @Summary 获取可移动目标知识库列表 @Description 返回与源知识库 Type 一致、EmbeddingModelID 一致、非临时且不是自身的目标知识库列表 @Tags 知识库 @Produce json @Param id path string true "源知识库 ID" @Success 200 {object} map[string]interface{} "可移动目标列表" @Failure 400 {object} errors.AppError "请求参数错误" @Failure 404 {object} errors.AppError "知识库不存在" @Security Bearer @Security ApiKeyAuth @Router /knowledge-bases/{id}/move-targets [get]

func (*KnowledgeBaseHandler) TogglePinKnowledgeBase

func (h *KnowledgeBaseHandler) TogglePinKnowledgeBase(c *gin.Context)

TogglePinKnowledgeBase godoc @Summary 置顶/取消置顶知识库 @Description 切换知识库的置顶状态 @Tags 知识库 @Accept json @Produce json @Param id path string true "知识库ID" @Success 200 {object} map[string]interface{} "更新后的知识库" @Failure 404 {object} errors.AppError "知识库不存在" @Security Bearer @Security ApiKeyAuth @Router /knowledge-bases/{id}/pin [put]

func (*KnowledgeBaseHandler) UpdateKnowledgeBase

func (h *KnowledgeBaseHandler) UpdateKnowledgeBase(c *gin.Context)

UpdateKnowledgeBase godoc @Summary 更新知识库 @Description 更新知识库的名称、描述和配置 @Tags 知识库 @Accept json @Produce json @Param id path string true "知识库ID" @Param request body UpdateKnowledgeBaseRequest true "更新请求" @Success 200 {object} map[string]interface{} "更新后的知识库" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /knowledge-bases/{id} [put]

type KnowledgeHandler

type KnowledgeHandler struct {
	// contains filtered or unexported fields
}

KnowledgeHandler processes HTTP requests related to knowledge resources

func NewKnowledgeHandler

func NewKnowledgeHandler(
	cfg *config.Config,
	kgService interfaces.KnowledgeService,
	kbService interfaces.KnowledgeBaseService,
	kbShareService interfaces.KBShareService,
	agentShareService interfaces.AgentShareService,
	chunkService interfaces.ChunkService,
	systemSettingSvc interfaces.SystemSettingService,
	userSvc interfaces.UserService,
	asynqClient interfaces.TaskEnqueuer,
	spanRepo repository.KnowledgeSpanRepository,
	housekeeping *service.HousekeepingService,
) *KnowledgeHandler

NewKnowledgeHandler creates a new knowledge handler instance

func (*KnowledgeHandler) BatchDeleteKnowledge

func (h *KnowledgeHandler) BatchDeleteKnowledge(c *gin.Context)

BatchDeleteKnowledge godoc @Summary 批量删除知识 @Description 按 ID 列表批量删除单个知识库下的多个知识条目 @Tags 知识管理 @Accept json @Produce json @Param request body BatchDeleteKnowledgeRequest true "批量删除请求" @Success 200 {object} map[string]interface{} "删除成功" @Failure 400 {object} errors.AppError "请求参数错误" @Failure 403 {object} errors.AppError "权限不足" @Security Bearer @Security ApiKeyAuth @Router /knowledge/batch-delete [post]

func (*KnowledgeHandler) BatchDownloadKnowledge

func (h *KnowledgeHandler) BatchDownloadKnowledge(c *gin.Context)

BatchDownloadKnowledge godoc @Summary 批量下载知识文件 @Description 将同一知识库的最多 200 个文档打包为 ZIP,原始内容合计不超过 512 MiB。无原文件的条目会被跳过;无权访问、跨库或读取失败时不返回残缺压缩包。 @Tags 知识管理 @Accept json @Produce application/zip @Param id path string true "知识库ID" @Param request body BatchDownloadKnowledgeRequest true "文档ID列表" @Success 200 {file} file "ZIP 压缩包" @Failure 400 {object} errors.AppError @Failure 401 {object} errors.AppError @Failure 403 {object} errors.AppError @Failure 404 {object} errors.AppError @Failure 429 {object} errors.AppError @Failure 500 {object} errors.AppError @Security Bearer @Security ApiKeyAuth @Router /knowledge-bases/{id}/knowledge/batch-download [post]

func (*KnowledgeHandler) BatchReparseKnowledge

func (h *KnowledgeHandler) BatchReparseKnowledge(c *gin.Context)

BatchReparseKnowledge godoc @Summary 批量重新解析知识 @Description 按 ID 列表批量重新解析单个知识库下的多个知识条目 @Tags 知识管理 @Accept json @Produce json @Param request body batchReparseKnowledgeRequest true "批量重解析请求" @Success 200 {object} map[string]interface{} "任务已提交" @Failure 400 {object} errors.AppError "请求参数错误" @Failure 403 {object} errors.AppError "权限不足" @Security Bearer @Security ApiKeyAuth @Router /knowledge/batch-reparse [post]

func (*KnowledgeHandler) CancelKnowledgeParse

func (h *KnowledgeHandler) CancelKnowledgeParse(c *gin.Context)

CancelKnowledgeParse godoc @Summary 取消知识解析 @Description 取消进行中的知识解析任务。当前已写入的 chunk / 索引保留,可通过 reparse 接口重新触发解析。已完成 / 已失败 / 删除中的知识不支持取消。 @Tags 知识管理 @Accept json @Produce json @Param id path string true "知识ID" @Success 200 {object} map[string]interface{} "取消已提交" @Failure 400 {object} errors.AppError "状态不支持取消" @Failure 403 {object} errors.AppError "权限不足" @Failure 404 {object} errors.AppError "知识不存在" @Security Bearer @Security ApiKeyAuth @Router /knowledge/{id}/cancel-parse [post]

func (*KnowledgeHandler) ClearKnowledgeBaseContents

func (h *KnowledgeHandler) ClearKnowledgeBaseContents(c *gin.Context)

ClearKnowledgeBaseContents godoc @Summary 清空知识库内容 @Description 删除知识库下的所有知识条目(异步任务)。知识库本身保留,仅清空其中的内容 @Tags 知识管理 @Accept json @Produce json @Param id path string true "知识库ID" @Success 200 {object} map[string]interface{} "清空任务已提交" @Failure 400 {object} errors.AppError "请求参数错误" @Failure 403 {object} errors.AppError "权限不足" @Security Bearer @Security ApiKeyAuth @Router /knowledge-bases/{id}/knowledge [delete]

func (*KnowledgeHandler) CreateKnowledgeFromFile

func (h *KnowledgeHandler) CreateKnowledgeFromFile(c *gin.Context)

CreateKnowledgeFromFile godoc @Summary 从文件创建知识 @Description 上传文件并创建知识条目 @Tags 知识管理 @Accept multipart/form-data @Produce json @Param id path string true "知识库ID" @Param file formData file true "上传的文件" @Param fileName formData string false "自定义文件名" @Param metadata formData string false "元数据JSON" @Param enable_multimodel formData bool false "启用多模态处理" @Param tag_ids formData string false "分类ID列表,逗号分隔" @Param process_config formData string false "处理配置JSON(KnowledgeProcessOverrides)" @Success 200 {object} map[string]interface{} "创建的知识" @Failure 400 {object} errors.AppError "请求参数错误" @Failure 409 {object} map[string]interface{} "文件重复" @Security Bearer @Security ApiKeyAuth @Router /knowledge-bases/{id}/knowledge/file [post]

func (*KnowledgeHandler) CreateKnowledgeFromURL

func (h *KnowledgeHandler) CreateKnowledgeFromURL(c *gin.Context)

CreateKnowledgeFromURL godoc @Summary 从URL创建知识 @Description 从指定URL抓取内容并创建知识条目。当提供 file_name/file_type 或 URL 路径含已知文件扩展名时,自动切换为文件下载模式 @Tags 知识管理 @Accept json @Produce json @Param id path string true "知识库ID" @Param request body object{url=string,file_name=string,file_type=string,enable_multimodel=bool,title=string,tag_ids=[]string} true "URL请求" @Success 201 {object} map[string]interface{} "创建的知识" @Failure 400 {object} errors.AppError "请求参数错误" @Failure 409 {object} map[string]interface{} "URL重复" @Security Bearer @Security ApiKeyAuth @Router /knowledge-bases/{id}/knowledge/url [post]

func (*KnowledgeHandler) CreateManualKnowledge

func (h *KnowledgeHandler) CreateManualKnowledge(c *gin.Context)

CreateManualKnowledge godoc @Summary 手工创建知识 @Description 手工录入Markdown格式的知识内容 @Tags 知识管理 @Accept json @Produce json @Param id path string true "知识库ID" @Param request body types.ManualKnowledgePayload true "手工知识内容" @Success 200 {object} map[string]interface{} "创建的知识" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /knowledge-bases/{id}/knowledge/manual [post]

func (*KnowledgeHandler) DeleteKnowledge

func (h *KnowledgeHandler) DeleteKnowledge(c *gin.Context)

DeleteKnowledge godoc @Summary 删除知识 @Description 根据ID异步删除知识条目。请求会被入队到与批量删除相同的异步管道(asynq); @Description 接口返回 200 仅表示任务已提交(响应 data.task_id 为任务 ID),实际删除由后台 worker 完成。 @Tags 知识管理 @Accept json @Produce json @Param id path string true "知识ID" @Success 200 {object} map[string]interface{} "任务已提交,返回 task_id" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /knowledge/{id} [delete]

func (*KnowledgeHandler) DownloadKnowledgeFile

func (h *KnowledgeHandler) DownloadKnowledgeFile(c *gin.Context)

DownloadKnowledgeFile godoc @Summary 下载知识文件 @Description 下载知识条目关联的原始文件 @Tags 知识管理 @Accept json @Produce application/octet-stream @Param id path string true "知识ID" @Success 200 {file} file "文件内容" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /knowledge/{id}/download [get]

func (*KnowledgeHandler) GetGalleryConfig

func (h *KnowledgeHandler) GetGalleryConfig(c *gin.Context)

GetGalleryConfig serves the gallery's self-describing contract: which attribute sources are live, every resolved attribute (definition + merged usage + which tier decided it), and the caller's search activation state (mode + per-field status). The frontend renders its filter panel, search field checkboxes and sort dropdown purely from this response — no gallery UI rule is hardcoded client-side.

func (*KnowledgeHandler) GetKnowledge

func (h *KnowledgeHandler) GetKnowledge(c *gin.Context)

GetKnowledge godoc @Summary 获取知识详情 @Description 根据ID获取知识条目详情 @Tags 知识管理 @Accept json @Produce json @Param id path string true "知识ID" @Success 200 {object} map[string]interface{} "知识详情" @Failure 400 {object} errors.AppError "请求参数错误" @Failure 404 {object} errors.AppError "知识不存在" @Security Bearer @Security ApiKeyAuth @Router /knowledge/{id} [get]

func (*KnowledgeHandler) GetKnowledgeBatch

func (h *KnowledgeHandler) GetKnowledgeBatch(c *gin.Context)

GetKnowledgeBatch godoc @Summary 批量获取知识 @Description 根据ID列表批量获取知识条目。可选 kb_id:指定时按该知识库校验权限并用于共享知识库的空间解析;可选 agent_id:使用共享智能体时传此参数,后端按智能体所属空间查询(用于刷新后恢复共享知识库下的文件) @Tags 知识管理 @Accept json @Produce json @Param ids query []string true "知识ID列表" @Param kb_id query string false "可选,知识库ID(用于共享知识库时指定范围)" @Param agent_id query string false "可选,共享智能体ID(用于按智能体空间批量拉取文件详情)" @Success 200 {object} map[string]interface{} "知识列表" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /knowledge/batch [get]

func (*KnowledgeHandler) GetKnowledgeMoveProgress

func (h *KnowledgeHandler) GetKnowledgeMoveProgress(c *gin.Context)

GetKnowledgeMoveProgress retrieves the progress of a knowledge move task.

GetKnowledgeMoveProgress godoc @Summary 获取知识移动进度 @Description 按任务 ID 查询移动进度 @Tags 知识 @Produce json @Param task_id path string true "移动任务 ID" @Success 200 {object} types.KnowledgeMoveProgress "进度信息" @Failure 404 {object} errors.AppError "任务不存在" @Security Bearer @Security ApiKeyAuth @Router /knowledge/move/progress/{task_id} [get]

func (*KnowledgeHandler) GetKnowledgeSpans

func (h *KnowledgeHandler) GetKnowledgeSpans(c *gin.Context)

GetKnowledgeSpans godoc @Summary 获取知识文档解析的 Span 树(含历史尝试) @Description 返回该知识在解析流水线的 trace tree(root → stage → subspan):每段状态、耗时、input/output、错误码、langfuse_trace_id。支持 ?attempt=N 查看历史尝试;不传则返回最新尝试。前端用于渲染时间线 + 多模态/embedding 子节点 + 一键跳转 Langfuse。 @Tags 知识管理 @Accept json @Produce json @Param id path string true "知识ID" @Param attempt query int false "指定尝试号;省略=最新" @Success 200 {object} map[string]interface{} @Security Bearer @Security ApiKeyAuth @Router /knowledge/{id}/spans [get]

Always returns the canonical 5-stage timeline; missing stage rows are synthesized as "pending" so the frontend timeline always renders five segments. Subspans (multimodal.image[i], generation.*) ride along under each stage as children when present.

func (*KnowledgeHandler) KBCreatorLookupFromKnowledgeID

func (h *KnowledgeHandler) KBCreatorLookupFromKnowledgeID(c *gin.Context) (string, error)

KBCreatorLookupFromKnowledgeID resolves :id (a Knowledge ID) to the CreatorID of the *owning KB*, scoped to the caller's tenant. Used by per-knowledge mutating routes (PR 5, #1303) so a Contributor who owns the KB can edit/delete any of its documents while a Contributor who merely belongs to the tenant cannot. Built-in / legacy KBs without a CreatorID surface as ("", nil) and stay Admin-gated.

The chain (knowledge_id -> kb_id -> KB.CreatorID) lives in the service layer (KnowledgeService.GetOwningKBCreatorID) so this lookup stays a pure adapter — same shape as KBCreatorLookup.

func (*KnowledgeHandler) ListImages

func (h *KnowledgeHandler) ListImages(c *gin.Context)

ListImages lists the image assets of a knowledge base for the gallery view.

@Summary 列出知识库图片资产 @Description 浏览某知识库内的全部图片资产,支持关键字搜索(caption/OCR 文本)、按图片属性筛选(attr_filters / attr_rules)与排序分页。 @Tags knowledge @Accept json @Produce json @Param id path string true "知识库 ID" @Param page query int false "页码,默认 1" @Param page_size query int false "每页数量,默认 20,最大 1000" @Param keyword query string false "关键字,对 search_in 指定字段做不区分大小写的子串匹配" @Param search_in query string false "参与搜索的属性 ID(逗号分隔);须为 in_searchfield=true" @Param sort_by query string false "排序属性 ID;须为 in_sortfield=true,默认 created_at" @Param sort_order query string false "排序方向:asc / desc,默认 desc" @Param is_enabled query bool false "仅包含启用状态的图片" @Param knowledge_ids query string false "来源文档 ID 列表(逗号分隔,最多 50 个),仅返回这些文档的图片" @Param attr_filters query string false "属性筛选 JSON,同一属性多值 OR、属性间 AND" @Param attr_rules query string false "属性逐值裁决 JSON(off 隐藏 / on 强制显示,on 优先)" @Success 200 {object} map[string]interface{} "图片资产分页列表" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /knowledge-bases/{id}/images [get]

func (*KnowledgeHandler) ListImagesPost

func (h *KnowledgeHandler) ListImagesPost(c *gin.Context)

ListImagesPost lists image assets like ListImages, with the filter arriving as a JSON body.

@Summary 列出知识库图片资产(body 版) @Description 与 GET /images 同义,筛选参数改经 JSON body 传递:knowledge_ids 不再受 URL 长度限制(上限 1000),供来源文档全选使用。 @Tags knowledge @Accept json @Produce json @Param id path string true "知识库 ID" @Param body body imageListRequestBody false "筛选参数(与 GET /images 同名参数同义)" @Success 200 {object} map[string]interface{} "图片资产分页列表" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /knowledge-bases/{id}/images [post]

func (*KnowledgeHandler) ListKnowledge

func (h *KnowledgeHandler) ListKnowledge(c *gin.Context)

ListKnowledge godoc @Summary 获取知识列表 @Description 获取知识库下的知识列表,支持分页和筛选 @Tags 知识管理 @Accept json @Produce json @Param id path string true "知识库ID" @Param page query int false "页码" @Param page_size query int false "每页数量" @Param tag_ids query string false "标签ID筛选,逗号分隔(OR语义)" @Param keyword query string false "关键词搜索" @Param file_type query string false "文件类型筛选" @Param parse_status query string false "解析状态筛选 (pending/processing/completed/failed)" @Param source query string false "来源/渠道筛选 (web/api/feishu/notion/yuque/wechat/...,或 manual/url 按 type 过滤)" @Param start_time query string false "更新时间起点,RFC3339 格式" @Param end_time query string false "更新时间终点,RFC3339 格式" @Param folder_path query string false "文件夹路径筛选,空字符串表示知识库根目录;不传该参数则不按文件夹过滤" @Param folder_recursive query bool false "为 true 时同时返回子文件夹内的文档" @Param sort_by query string false "排序字段: updated_at/created_at/file_name,默认 created_at" @Param sort_order query string false "排序方向: asc/desc,默认 desc" @Success 200 {object} map[string]interface{} "知识列表" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /knowledge-bases/{id}/knowledge [get]

func (*KnowledgeHandler) ListKnowledgeFolders

func (h *KnowledgeHandler) ListKnowledgeFolders(c *gin.Context)

ListKnowledgeFolders godoc @Summary 获取知识库文件夹目录树 @Description 返回知识库内由文件夹上传形成的目录树,包含每个文件夹的直接文档数与含子目录的总数 @Tags 知识管理 @Accept json @Produce json @Param id path string true "知识库ID" @Success 200 {object} map[string]interface{} "目录树" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /knowledge-bases/{id}/knowledge/folders [get]

func (*KnowledgeHandler) MoveKnowledge

func (h *KnowledgeHandler) MoveKnowledge(c *gin.Context)

MoveKnowledge moves knowledge items from one knowledge base to another (async task).

MoveKnowledge godoc @Summary 移动知识到其他知识库 @Description 将一条或多条知识从源知识库移动到目标知识库(异步),返回任务 ID 用于查询进度 @Tags 知识 @Accept json @Produce json @Param request body handler.MoveKnowledgeRequest true "{source_kb_id, target_kb_id, knowledge_ids}" @Success 200 {object} handler.MoveKnowledgeResponse "任务信息" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /knowledge/move [post]

func (*KnowledgeHandler) MoveKnowledgeToFolder

func (h *KnowledgeHandler) MoveKnowledgeToFolder(c *gin.Context)

MoveKnowledgeToFolder godoc @Summary 移动知识到文件夹 @Description 批量修改知识条目所属文件夹。文件夹由路径推导而来,因此目标路径不存在时会自动创建;空路径表示知识库顶层。仅调整归类,不会重新解析文档 @Tags 知识管理 @Accept json @Produce json @Param request body MoveKnowledgeToFolderRequest true "移动请求" @Success 200 {object} map[string]interface{} "移动成功" @Failure 400 {object} errors.AppError "请求参数错误" @Failure 403 {object} errors.AppError "权限不足" @Security Bearer @Security ApiKeyAuth @Router /knowledge/folder [post]

func (*KnowledgeHandler) PreviewKnowledgeFile

func (h *KnowledgeHandler) PreviewKnowledgeFile(c *gin.Context)

PreviewKnowledgeFile godoc @Summary 预览知识文件 @Description 返回知识条目关联的原始文件,Content-Type 根据文件类型设置,用于浏览器内嵌预览 @Tags 知识管理 @Accept json @Produce application/pdf,image/jpeg,image/png,text/plain @Param id path string true "知识ID" @Success 200 {file} file "文件内容" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /knowledge/{id}/preview [get]

func (*KnowledgeHandler) RegenerateKnowledgeSummary

func (h *KnowledgeHandler) RegenerateKnowledgeSummary(c *gin.Context)

RegenerateKnowledgeSummary refreshes a stale summary after chunk or metadata edits.

func (*KnowledgeHandler) RenameKnowledgeFolder

func (h *KnowledgeHandler) RenameKnowledgeFolder(c *gin.Context)

RenameKnowledgeFolder godoc @Summary 重命名或移动文件夹 @Description 把一个文件夹及其所有子目录改到新路径。目标路径已存在时两个文件夹合并;不能移动到自身子目录下 @Tags 知识管理 @Accept json @Produce json @Param id path string true "知识库ID" @Param request body RenameKnowledgeFolderRequest true "重命名请求" @Success 200 {object} map[string]interface{} "重命名成功" @Failure 400 {object} errors.AppError "请求参数错误" @Failure 403 {object} errors.AppError "权限不足" @Security Bearer @Security ApiKeyAuth @Router /knowledge-bases/{id}/knowledge/folders [put]

func (*KnowledgeHandler) ReparseKnowledge

func (h *KnowledgeHandler) ReparseKnowledge(c *gin.Context)

ReparseKnowledge godoc @Summary 重新解析知识 @Description 删除知识中现有的文档内容并重新解析,使用异步任务方式处理 @Tags 知识管理 @Accept json @Produce json @Param id path string true "知识ID" @Param body body object false "可选的处理配置覆盖:{\"process_config\": KnowledgeProcessOverrides}" @Success 200 {object} map[string]interface{} "重新解析任务已提交" @Failure 400 {object} errors.AppError "请求参数错误" @Failure 403 {object} errors.AppError "权限不足" @Security Bearer @Security ApiKeyAuth @Router /knowledge/{id}/reparse [post]

func (*KnowledgeHandler) SearchKnowledge

func (h *KnowledgeHandler) SearchKnowledge(c *gin.Context)

SearchKnowledge godoc @Summary Search knowledge @Description Search knowledge files by keyword. Pass recent=true without a keyword to browse recent files. When agent_id is set (shared agent), scope is the agent's configured knowledge bases. @Tags Knowledge @Accept json @Produce json @Param keyword query string false "Keyword to search" @Param offset query int false "Offset for pagination (minimum 0)" minimum(0) @Param limit query int false "Limit for pagination (default 20, maximum 100)" minimum(1) maximum(100) @Param file_types query string false "Comma-separated file extensions to filter (e.g., csv,xlsx)" @Param agent_id query string false "Shared agent ID (search within agent's KB scope)" @Param recent query bool false "Return recent files when keyword is empty" @Success 200 {object} map[string]interface{} "Search results" @Failure 400 {object} errors.AppError "Invalid request" @Security Bearer @Security ApiKeyAuth @Router /knowledge/search [get]

func (*KnowledgeHandler) UpdateImageInfo

func (h *KnowledgeHandler) UpdateImageInfo(c *gin.Context)

UpdateImageInfo godoc @Summary 更新图像信息 @Description 更新知识分块的图像信息 @Tags 知识管理 @Accept json @Produce json @Param id path string true "知识ID" @Param chunk_id path string true "分块ID" @Param request body object{image_info=string} true "图像信息" @Success 200 {object} map[string]interface{} "更新成功" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /knowledge/image/{id}/{chunk_id} [put]

func (*KnowledgeHandler) UpdateKnowledge

func (h *KnowledgeHandler) UpdateKnowledge(c *gin.Context)

UpdateKnowledge godoc @Summary 更新知识 @Description 部分更新知识条目(标题/描述/自定义元数据);未传字段保持不变,显式传空 description 可清空摘要 @Tags 知识管理 @Accept json @Produce json @Param id path string true "知识ID" @Param request body UpdateKnowledgeRequest true "更新字段(均可选)" @Success 200 {object} map[string]interface{} "更新成功" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /knowledge/{id} [put]

func (*KnowledgeHandler) UpdateKnowledgeTagBatch

func (h *KnowledgeHandler) UpdateKnowledgeTagBatch(c *gin.Context)

UpdateKnowledgeTagBatch godoc @Summary 批量更新知识标签 @Description 批量更新知识条目的标签。可选 kb_id:指定时按该知识库校验编辑权限并用于共享知识库的空间解析 @Tags 知识管理 @Accept json @Produce json @Param request body object true "标签更新请求(updates 必填,kb_id 可选)" @Success 200 {object} map[string]interface{} "更新成功" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /knowledge/tags [put]

func (*KnowledgeHandler) UpdateManualKnowledge

func (h *KnowledgeHandler) UpdateManualKnowledge(c *gin.Context)

UpdateManualKnowledge godoc @Summary 更新手工知识 @Description 更新手工录入的Markdown知识内容 @Tags 知识管理 @Accept json @Produce json @Param id path string true "知识ID" @Param request body types.ManualKnowledgePayload true "手工知识内容" @Success 200 {object} map[string]interface{} "更新后的知识" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /knowledge/manual/{id} [put]

type ListAllUsersResponse

type ListAllUsersResponse struct {
	Users   []*types.UserInfo `json:"users"`
	Offset  int               `json:"offset"`
	Limit   int               `json:"limit"`
	HasMore bool              `json:"has_more"`
}

ListAllUsersResponse is the paginated payload for the platform user list. Unlike the system-admin list there is no total COUNT; HasMore tells the UI whether a next page exists (derived by fetching limit+1 rows).

type ListSystemAdminsResponse

type ListSystemAdminsResponse struct {
	Total  int64             `json:"total"`
	Admins []*types.UserInfo `json:"admins"`
}

ListSystemAdminsResponse defines the response structure for listing system admins. Total reflects the underlying COUNT(*), not just the page size, so the front end can render pagination metadata without a follow-up call.

type MCPCredentialsHandler

type MCPCredentialsHandler struct {
	// contains filtered or unexported fields
}

MCPCredentialsHandler handles secret credentials for MCP services via a dedicated subresource (/mcp-services/{id}/credentials). Splitting this out of UpdateMCPService delivers three concrete benefits:

  1. The main MCP PUT body never carries secrets — eliminating the "masked-value round-trip overwrites stored secret" class of bug at the contract level rather than via runtime preserve-on-redacted defenses.

  2. Saving the MCP edit dialog (changing timeout / enabled / etc.) cannot accidentally invalidate or clobber a working credential. Credential operations are explicit and atomic.

  3. The "is this configured?" metadata travels on the main resource response (MCPServiceResponse.Credentials) — no separate GET endpoint needed. Only PUT and DELETE live here.

func NewMCPCredentialsHandler

func NewMCPCredentialsHandler(svc interfaces.MCPServiceService) *MCPCredentialsHandler

NewMCPCredentialsHandler constructs the handler.

func (*MCPCredentialsHandler) DeleteField

func (h *MCPCredentialsHandler) DeleteField(c *gin.Context)

DeleteField removes one credential field. Recognized fields: "api_key", "token", "client_secret". Returns 204 on success (even if the field was already empty).

DeleteField godoc @Summary 移除 MCP 服务的单个凭据字段 @Description 删除指定字段的存储凭据;删除已为空的字段是幂等的 @Tags MCP服务 @Produce json @Param id path string true "MCP 服务 ID" @Param field path string true "字段名(api_key | token | client_secret)" @Success 204 @Failure 400 {object} errors.AppError "字段名非法" @Failure 404 {object} errors.AppError "服务不存在" @Security Bearer @Security ApiKeyAuth @Router /mcp-services/{id}/credentials/{field} [delete]

func (*MCPCredentialsHandler) Put

func (h *MCPCredentialsHandler) Put(c *gin.Context)

Put writes (creates or replaces) one or more credential fields on the MCP service. Triggers a connection recycle so the next upstream call uses the new credential.

Put godoc @Summary 设置 MCP 服务凭据 @Description 为指定字段写入新凭据;省略的字段保留原值;空字符串视为 no-op(如需删除请用 DELETE) @Tags MCP服务 @Accept json @Produce json @Param id path string true "MCP 服务 ID" @Param request body map[string]interface{} true "{api_key?, token?, client_secret?: string}" @Success 200 {object} map[string]interface{} "写入后的凭据状态" @Failure 400 {object} errors.AppError "请求参数错误" @Failure 404 {object} errors.AppError "服务不存在" @Security Bearer @Security ApiKeyAuth @Router /mcp-services/{id}/credentials [put]

type MCPEndpointHandler

type MCPEndpointHandler struct {
	// contains filtered or unexported fields
}

MCPEndpointHandler manages the workspace's published MCP server endpoints.

func NewMCPEndpointHandler

func NewMCPEndpointHandler(svc interfaces.MCPEndpointService) *MCPEndpointHandler

NewMCPEndpointHandler creates the MCP endpoint management handler.

func (*MCPEndpointHandler) CreateMCPEndpoint

func (h *MCPEndpointHandler) CreateMCPEndpoint(c *gin.Context)

CreateMCPEndpoint creates an endpoint and returns it with the one-time token.

@Summary 创建 MCP 端点 @Description 为当前工作空间发布一个 MCP 端点,响应中的 token 只返回一次 @Tags MCP端点 @Accept json @Produce json @Param request body object true "端点配置:name、description、enabled、knowledge_base_ids、tools 等" @Success 201 {object} map[string]interface{} "创建的端点,含一次性 token" @Failure 400 {object} map[string]interface{} "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /mcp-endpoints [post]

func (*MCPEndpointHandler) DeleteMCPEndpoint

func (h *MCPEndpointHandler) DeleteMCPEndpoint(c *gin.Context)

DeleteMCPEndpoint soft-deletes an endpoint; connected clients lose access.

@Summary 删除 MCP 端点 @Tags MCP端点 @Produce json @Param endpoint_id path string true "端点 ID" @Success 200 {object} map[string]interface{} "删除成功" @Failure 404 {object} map[string]interface{} "端点不存在" @Security Bearer @Security ApiKeyAuth @Router /mcp-endpoints/{endpoint_id} [delete]

func (*MCPEndpointHandler) GetMCPEndpoint

func (h *MCPEndpointHandler) GetMCPEndpoint(c *gin.Context)

GetMCPEndpoint returns one endpoint.

@Summary 获取 MCP 端点详情 @Tags MCP端点 @Produce json @Param endpoint_id path string true "端点 ID" @Success 200 {object} map[string]interface{} "端点详情" @Failure 404 {object} map[string]interface{} "端点不存在" @Security Bearer @Security ApiKeyAuth @Router /mcp-endpoints/{endpoint_id} [get]

func (*MCPEndpointHandler) ListMCPEndpoints

func (h *MCPEndpointHandler) ListMCPEndpoints(c *gin.Context)

ListMCPEndpoints lists the workspace endpoints without tokens.

@Summary 获取 MCP 端点列表 @Tags MCP端点 @Produce json @Success 200 {object} map[string]interface{} "端点列表" @Security Bearer @Security ApiKeyAuth @Router /mcp-endpoints [get]

func (*MCPEndpointHandler) ListToolCatalog

func (h *MCPEndpointHandler) ListToolCatalog(c *gin.Context)

ListToolCatalog returns the tools an endpoint can expose, grouped.

@Summary 获取 MCP 端点工具目录 @Description 返回工作空间 MCP 端点可勾选的工具清单、分组和默认勾选项 @Tags MCP端点 @Produce json @Success 200 {object} map[string]interface{} "工具目录" @Security Bearer @Security ApiKeyAuth @Router /mcp-endpoints/tools [get]

func (*MCPEndpointHandler) RotateMCPEndpointToken

func (h *MCPEndpointHandler) RotateMCPEndpointToken(c *gin.Context)

RotateMCPEndpointToken issues a fresh token and returns it once.

@Summary 轮换 MCP 端点令牌 @Description 生成新令牌并立即作废旧令牌,响应中的 token 只返回一次 @Tags MCP端点 @Produce json @Param endpoint_id path string true "端点 ID" @Success 200 {object} map[string]interface{} "含新 token 的端点" @Failure 404 {object} map[string]interface{} "端点不存在" @Security Bearer @Security ApiKeyAuth @Router /mcp-endpoints/{endpoint_id}/rotate-token [post]

func (*MCPEndpointHandler) UpdateMCPEndpoint

func (h *MCPEndpointHandler) UpdateMCPEndpoint(c *gin.Context)

UpdateMCPEndpoint applies a partial update; omitted fields are kept.

@Summary 更新 MCP 端点 @Tags MCP端点 @Accept json @Produce json @Param endpoint_id path string true "端点 ID" @Param request body object true "要更新的字段,未提供的字段保持不变" @Success 200 {object} map[string]interface{} "更新后的端点" @Failure 400 {object} map[string]interface{} "请求参数错误" @Failure 404 {object} map[string]interface{} "端点不存在" @Security Bearer @Security ApiKeyAuth @Router /mcp-endpoints/{endpoint_id} [put]

type MCPOAuthHandler

type MCPOAuthHandler struct {
	// contains filtered or unexported fields
}

MCPOAuthHandler exposes the per-user MCP OAuth2 authorization-code flow: kicking off authorization (discovery + dynamic client registration + PKCE), receiving the provider redirect, reporting authorization status, and revoking a user's token.

func NewMCPOAuthHandler

func NewMCPOAuthHandler(
	oauth *mcp.OAuthManager,
	mcpManager *mcp.MCPManager,
	svc interfaces.MCPServiceService,
	gate *approval.Gate,
) *MCPOAuthHandler

NewMCPOAuthHandler constructs the handler.

func (*MCPOAuthHandler) AssertionGrant

func (h *MCPOAuthHandler) AssertionGrant(c *gin.Context)

AssertionGrant obtains the current user's token with the JWT bearer grant (RFC 7523) instead of the browser authorization code flow. It is for applications that run WeKnora behind their own sign-in and call it for their users, where no browser can follow an authorization redirect. The grant uses the OAuth client already registered for the service, and the token is stored exactly like one obtained through the callback.

AssertionGrant godoc @Summary 使用断言获取 MCP OAuth 令牌 @Description 以 JWT Bearer 授权(RFC 7523)提交调用方签发的断言(如 ID-JAG),为当前用户获取并保存令牌, @Description 无需浏览器跳转。使用该服务已注册的 OAuth 客户端 @Tags MCP服务 @Accept json @Produce json @Param id path string true "MCP 服务 ID" @Param request body map[string]interface{} true "{assertion: string}" @Success 200 {object} map[string]interface{} "与 oauth/status 相同" @Failure 400 {object} errors.AppError "断言无效或被授权服务器拒绝" @Failure 404 {object} errors.AppError @Security Bearer @Router /mcp-services/{id}/oauth/assertion [post]

func (*MCPOAuthHandler) AuthorizeURL

func (h *MCPOAuthHandler) AuthorizeURL(c *gin.Context)

AuthorizeURL begins authorization and returns the URL the browser must open.

AuthorizeURL godoc @Summary 发起 MCP OAuth 授权 @Description 对使用 OAuth 的 MCP 服务执行发现与动态客户端注册,返回浏览器应跳转的授权地址(当前用户维度) @Tags MCP服务 @Accept json @Produce json @Param id path string true "MCP 服务 ID" @Param request body map[string]interface{} true "{redirect_uri: string, frontend_redirect?: string}" @Success 200 {object} map[string]interface{} "{authorization_url: string, authorization_attempt: string}" @Failure 400 {object} errors.AppError @Security Bearer @Router /mcp-services/{id}/oauth/authorize-url [post]

func (*MCPOAuthHandler) Callback

func (h *MCPOAuthHandler) Callback(c *gin.Context)

Callback receives the authorization-server redirect. It is registered as a public (no-bearer) route; the opaque single-use `state` parameter authenticates the request. On completion it redirects the browser back to the frontend with the result encoded in the URL fragment.

Callback godoc @Summary MCP OAuth 回调 @Description 接收授权服务器回调并完成 code 交换,随后重定向回前端 @Tags MCP服务 @Param code query string false "授权码" @Param state query string false "状态参数" @Param error query string false "授权错误码" @Success 302 @Router /mcp-services/oauth/callback [get]

func (*MCPOAuthHandler) CancelMCPOAuth

func (h *MCPOAuthHandler) CancelMCPOAuth(c *gin.Context)

CancelMCPOAuth lets the user skip an in-conversation OAuth prompt without completing authorization. This unblocks the paused agent with a denial.

CancelMCPOAuth godoc @Summary 跳过对话内 MCP OAuth 授权 @Description 用户主动跳过 OAuth 授权,解除 Agent 阻塞 @Tags MCP服务 @Produce json @Param pending_id path string true "待授权 ID" @Success 200 {object} map[string]interface{} @Failure 404 {object} errors.AppError @Security Bearer @Router /agent/mcp-oauth-resolutions/{pending_id}/cancel [post]

func (*MCPOAuthHandler) ResolveMCPOAuth

func (h *MCPOAuthHandler) ResolveMCPOAuth(c *gin.Context)

ResolveMCPOAuth resumes an agent run that paused on an in-conversation OAuth prompt. The frontend calls this once the per-user authorization popup has completed; the backend verifies a token now exists for (tenant, user, service) before unblocking, so a premature/failed authorization does not resume the tool into another failure.

ResolveMCPOAuth godoc @Summary 完成对话内 MCP OAuth 授权 @Description 用户在对话中完成 OAuth 授权后调用,校验令牌存在后恢复被暂停的 Agent 工具调用 @Tags MCP服务 @Accept json @Produce json @Param pending_id path string true "待授权 ID" @Param request body map[string]interface{} true "{service_id: string}" @Success 200 {object} map[string]interface{} @Failure 400 {object} errors.AppError @Failure 409 {object} errors.AppError "用户尚未完成授权" @Security Bearer @Router /agent/mcp-oauth-resolutions/{pending_id} [post]

func (*MCPOAuthHandler) Revoke

func (h *MCPOAuthHandler) Revoke(c *gin.Context)

Revoke removes the current user's stored token and recycles their connection.

Revoke godoc @Summary 撤销 MCP OAuth 授权 @Description 删除当前用户对指定 MCP 服务的 OAuth 令牌 @Tags MCP服务 @Produce json @Param id path string true "MCP 服务 ID" @Success 204 @Security Bearer @Router /mcp-services/{id}/oauth/token [delete]

func (*MCPOAuthHandler) Status

func (h *MCPOAuthHandler) Status(c *gin.Context)

Status reports whether the current user has authorized this service.

Status godoc @Summary 查询 MCP OAuth 授权状态 @Description 返回当前用户的 OAuth Token 生命周期状态;传 authorization_attempt 时只检查本次授权流程 @Tags MCP服务 @Produce json @Param id path string true "MCP 服务 ID" @Param authorization_attempt query string false "本次授权尝试 ID;传入后不会接受历史 Token" @Success 200 {object} map[string]interface{} "{authorized: bool, state: string, refresh_available: bool, expires_at?: string}" @Security Bearer @Router /mcp-services/{id}/oauth/status [get]

type MCPServiceHandler

type MCPServiceHandler struct {
	// contains filtered or unexported fields
}

MCPServiceHandler handles MCP service related HTTP requests

func NewMCPServiceHandler

func NewMCPServiceHandler(
	mcpServiceService interfaces.MCPServiceService,
	mcpToolApprovalService interfaces.MCPToolApprovalService,
	toolApprovalGate *approval.Gate,
	modelService interfaces.ModelService,
	agents access.SharedAgentLookup,
) *MCPServiceHandler

NewMCPServiceHandler creates a new MCP service handler

func (*MCPServiceHandler) CreateMCPService

func (h *MCPServiceHandler) CreateMCPService(c *gin.Context)

CreateMCPService godoc @Summary 创建MCP服务 @Description 创建新的MCP服务配置 @Tags MCP服务 @Accept json @Produce json @Param request body types.MCPService true "MCP服务配置" @Success 200 {object} map[string]interface{} "创建的MCP服务" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /mcp-services [post]

func (*MCPServiceHandler) DeleteMCPService

func (h *MCPServiceHandler) DeleteMCPService(c *gin.Context)

DeleteMCPService godoc @Summary 删除MCP服务 @Description 删除指定的MCP服务 @Tags MCP服务 @Accept json @Produce json @Param id path string true "MCP服务ID" @Success 200 {object} map[string]interface{} "删除成功" @Failure 500 {object} errors.AppError "服务器错误" @Security Bearer @Security ApiKeyAuth @Router /mcp-services/{id} [delete]

func (*MCPServiceHandler) GenerateMCPUsageInstructions

func (h *MCPServiceHandler) GenerateMCPUsageInstructions(c *gin.Context)

GenerateMCPUsageInstructions uses the caller's saved directory, without connecting to MCP, executing tools, or persisting generated text.

func (*MCPServiceHandler) GetMCPMetadata

func (h *MCPServiceHandler) GetMCPMetadata(c *gin.Context)

GetMCPMetadata godoc @Summary 读取已保存的 MCP 工具目录 @Description 只读数据库,不连接上游。未同步时 data 为 null;连接配置变更后 stale 为 true。OAuth 目录按当前授权主体隔离。 @Tags MCP服务 @Accept json @Produce json @Param id path string true "MCP服务ID" @Success 200 {object} map[string]interface{} "目录快照" @Failure 400 {object} errors.AppError "请求参数错误" @Failure 401 {object} errors.AppError "OAuth 目录缺少授权主体" @Failure 404 {object} errors.AppError "服务不存在" @Security Bearer @Security ApiKeyAuth @Router /mcp-services/{id}/metadata [get]

func (*MCPServiceHandler) GetMCPService

func (h *MCPServiceHandler) GetMCPService(c *gin.Context)

GetMCPService godoc @Summary 获取MCP服务详情 @Description 根据ID获取MCP服务详情 @Tags MCP服务 @Accept json @Produce json @Param id path string true "MCP服务ID" @Success 200 {object} map[string]interface{} "MCP服务详情" @Failure 404 {object} errors.AppError "服务不存在" @Security Bearer @Security ApiKeyAuth @Router /mcp-services/{id} [get]

func (*MCPServiceHandler) GetMCPServiceResources

func (h *MCPServiceHandler) GetMCPServiceResources(c *gin.Context)

GetMCPServiceResources godoc @Summary 获取MCP服务资源列表 @Description 获取MCP服务提供的资源列表 @Tags MCP服务 @Accept json @Produce json @Param id path string true "MCP服务ID" @Success 200 {object} map[string]interface{} "资源列表" @Failure 500 {object} errors.AppError "服务器错误" @Security Bearer @Security ApiKeyAuth @Router /mcp-services/{id}/resources [get]

func (*MCPServiceHandler) GetMCPServiceTools

func (h *MCPServiceHandler) GetMCPServiceTools(c *gin.Context)

GetMCPServiceTools godoc @Summary 获取MCP服务工具列表 @Description 获取MCP服务提供的工具列表 @Tags MCP服务 @Accept json @Produce json @Param id path string true "MCP服务ID" @Success 200 {object} map[string]interface{} "工具列表" @Failure 500 {object} errors.AppError "服务器错误" @Security Bearer @Security ApiKeyAuth @Router /mcp-services/{id}/tools [get]

func (*MCPServiceHandler) ListMCPServices

func (h *MCPServiceHandler) ListMCPServices(c *gin.Context)

ListMCPServices godoc @Summary 获取MCP服务列表 @Description 获取当前空间的所有MCP服务(含已保存工具目录数量) @Tags MCP服务 @Accept json @Produce json @Param agent_id query string false "Agent ID; needs agent_source_tenant_id" @Param agent_source_tenant_id query int false "Shared agent source workspace" @Success 200 {object} map[string]interface{} "MCP服务列表" @Failure 400 {object} errors.AppError "请求参数错误" @Failure 403 {object} errors.AppError "无权使用该共享智能体" @Security Bearer @Security ApiKeyAuth @Router /mcp-services [get]

func (*MCPServiceHandler) ListMCPToolApprovals

func (h *MCPServiceHandler) ListMCPToolApprovals(c *gin.Context)

ListMCPToolApprovals returns persisted per-tool policies for an MCP service.

func (*MCPServiceHandler) RefreshMCPMetadata

func (h *MCPServiceHandler) RefreshMCPMetadata(c *gin.Context)

RefreshMCPMetadata godoc @Summary 同步 MCP 工具目录 @Description 显式连接上游并原子替换完整目录。OAuth 服务写入当前用户的快照,Viewer 及以上可调用;静态认证写入租户共享快照,需要 Admin。 @Tags MCP服务 @Accept json @Produce json @Param id path string true "MCP服务ID" @Success 200 {object} map[string]interface{} "同步后的目录快照" @Failure 400 {object} errors.AppError "目录不完整或校验失败" @Failure 401 {object} errors.AppError "OAuth 目录缺少授权主体" @Failure 403 {object} errors.AppError "静态认证目录需要管理员刷新" @Failure 404 {object} errors.AppError "服务不存在" @Failure 409 {object} errors.AppError "刷新期间连接配置已变更" @Failure 503 {object} errors.AppError "元数据存储不可用" @Security Bearer @Security ApiKeyAuth @Router /mcp-services/{id}/metadata/refresh [post]

func (*MCPServiceHandler) ResolveToolApproval

func (h *MCPServiceHandler) ResolveToolApproval(c *gin.Context)

ResolveToolApproval completes a pending MCP tool approval (agent execution resumes).

ResolveToolApproval godoc @Summary 处理 MCP 工具调用待审批请求 @Description 用户审批通过或驳回一次工具调用(用于 Agent 阻塞等待审批的场景) @Tags MCP服务 @Accept json @Produce json @Param pending_id path string true "待审批记录 ID" @Param request body map[string]interface{} true "{decision: \"approve\"|\"reject\", reason?: string, modified_args?: object}" @Success 200 {object} map[string]interface{} "审批结果" @Failure 400 {object} errors.AppError "请求参数错误" @Failure 404 {object} errors.AppError "待审批记录不存在" @Security Bearer @Security ApiKeyAuth @Router /agent/tool-approvals/{pending_id} [post]

func (*MCPServiceHandler) SetMCPToolApproval

func (h *MCPServiceHandler) SetMCPToolApproval(c *gin.Context)

SetMCPToolApproval updates per-tool MCP policy fields. The route name is kept for backwards compatibility with the original approval-only endpoint.

SetMCPToolApproval godoc @Summary 设置 MCP 工具策略 @Description 为指定 MCP 服务下的某个工具更新启用状态和/或人工审批要求。至少提供 require_approval 或 enabled 之一;省略的字段保持原值。 @Tags MCP服务 @Accept json @Produce json @Param id path string true "MCP 服务 ID" @Param tool_name path string true "工具名" @Param request body map[string]interface{} true "{require_approval?: bool, enabled?: bool}" @Success 200 {object} map[string]interface{} "更新结果" @Failure 400 {object} errors.AppError "请求参数错误" @Failure 404 {object} errors.AppError "MCP 服务或工具不存在" @Security Bearer @Security ApiKeyAuth @Router /mcp-services/{id}/tool-approvals/{tool_name} [put]

func (*MCPServiceHandler) TestMCPService

func (h *MCPServiceHandler) TestMCPService(c *gin.Context)

TestMCPService godoc @Summary 测试MCP服务连接 @Description 测试MCP服务是否可以正常连接 @Tags MCP服务 @Accept json @Produce json @Param id path string true "MCP服务ID" @Success 200 {object} map[string]interface{} "测试结果" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /mcp-services/{id}/test [post]

func (*MCPServiceHandler) UpdateMCPService

func (h *MCPServiceHandler) UpdateMCPService(c *gin.Context)

UpdateMCPService godoc @Summary 更新MCP服务 @Description 更新MCP服务配置 @Tags MCP服务 @Accept json @Produce json @Param id path string true "MCP服务ID" @Param request body object true "更新字段" @Success 200 {object} map[string]interface{} "更新后的MCP服务" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /mcp-services/{id} [put]

type MeEnvVarHandler

type MeEnvVarHandler struct {
	// contains filtered or unexported fields
}

MeEnvVarHandler serves the /me/env-vars endpoints.

These exist instead of relaxing /sandbox-configs/:id/skills*, which is Admin+ even for reads on purpose: an upload there drives a root shell whose output is baked into the image every session of that config boots, and the listing names what that image carries. This handler returns declarations and set/unset status only — never a value.

func NewMeEnvVarHandler

func NewMeEnvVarHandler(s *service.UserEnvService) *MeEnvVarHandler

func (*MeEnvVarHandler) DeleteSandbox

func (h *MeEnvVarHandler) DeleteSandbox(c *gin.Context)

DeleteSandbox godoc @Summary Delete one of my sandbox environment variables @Description Remove the caller's own value for one variable on a sandbox config. @Tags Me @Accept json @Produce json @Param request body meEnvVarRequest true "Sandbox config and variable name" @Success 200 {object} map[string]interface{} "Deleted" @Failure 404 {object} apperrors.AppError "Not set" @Security Bearer @Router /me/env-vars/sandbox [delete]

func (*MeEnvVarHandler) DeleteSkill

func (h *MeEnvVarHandler) DeleteSkill(c *gin.Context)

DeleteSkill godoc @Summary Delete one of my skill credentials @Description Remove the caller's own value. The workspace-wide value, if there is one, applies again afterwards. @Tags Me @Accept json @Produce json @Param request body meEnvVarRequest true "Skill and variable name" @Success 200 {object} map[string]interface{} "Deleted" @Failure 404 {object} apperrors.AppError "Not set" @Security Bearer @Router /me/env-vars/skill [delete]

func (*MeEnvVarHandler) List

func (h *MeEnvVarHandler) List(c *gin.Context)

List godoc @Summary List my environment variables @Description List every sandbox config of this workspace with the caller's own config-wide variables and the credentials its skills declared, each reporting whether it is unset, filled in workspace-wide, or filled in by the caller. Values are never returned. @Tags Me @Produce json @Success 200 {object} map[string]interface{} "One group per sandbox config" @Failure 401 {object} map[string]interface{} "Unauthorized" @Security Bearer @Router /me/env-vars [get]

func (*MeEnvVarHandler) SetSandbox

func (h *MeEnvVarHandler) SetSandbox(c *gin.Context)

SetSandbox godoc @Summary Set one of my sandbox environment variables @Description Store the caller's own value for one variable on a sandbox config. It is injected into every skill script and shell command this caller's turns run on that config. @Tags Me @Accept json @Produce json @Param request body meEnvVarRequest true "Sandbox config, variable name and value" @Success 200 {object} map[string]interface{} "Stored" @Failure 400 {object} apperrors.AppError "Invalid request" @Security Bearer @Router /me/env-vars/sandbox [put]

func (*MeEnvVarHandler) SetSkill

func (h *MeEnvVarHandler) SetSkill(c *gin.Context)

SetSkill godoc @Summary Set one of my skill credentials @Description Store the caller's own value for one variable the skill declared. It overrides the workspace-wide value for this caller only, and is injected only into executions that name this skill. @Tags Me @Accept json @Produce json @Param request body meEnvVarRequest true "Skill, variable name and value" @Success 200 {object} map[string]interface{} "Stored" @Failure 400 {object} apperrors.AppError "Invalid request" @Security Bearer @Router /me/env-vars/skill [put]

type MemoryHandler

type MemoryHandler struct {
	// contains filtered or unexported fields
}

MemoryHandler exposes the caller's own long-term memory.

Every route operates on the memory space derived from the request context, so no endpoint takes a subject id. That is deliberate: it removes the entire class of "can I read another user's memories by changing an id" bugs instead of relying on a per-route ownership check.

func NewMemoryHandler

func NewMemoryHandler(memoryService interfaces.MemoryService) *MemoryHandler

func (*MemoryHandler) Clear

func (h *MemoryHandler) Clear(c *gin.Context)

Clear godoc @Summary 清空我的记忆 @Description 永久删除当前用户的全部记忆 @Tags 长期记忆 @Produce json @Success 200 {object} map[string]interface{} "清空成功" @Security Bearer @Router /memory/items [delete]

func (*MemoryHandler) ConfirmItem

func (h *MemoryHandler) ConfirmItem(c *gin.Context)

ConfirmItem godoc @Summary 确认一条推断出的记忆 @Description 接受系统推断的记忆,使其开始生效 @Tags 长期记忆 @Produce json @Param id path string true "记忆 ID" @Success 200 {object} map[string]interface{} "确认成功" @Security Bearer @Router /memory/items/{id}/confirm [post]

Inferred memories are the ones worth having and the ones most likely to be wrong, so they wait here rather than taking effect silently.

func (*MemoryHandler) Consolidate

func (h *MemoryHandler) Consolidate(c *gin.Context)

Consolidate godoc @Summary 立刻整理我的记忆 @Description 合并意思接近的条目、归档到期事项,不等待每日后台整理 @Tags 长期记忆 @Produce json @Success 200 {object} map[string]interface{} "整理结果" @Security Bearer @Router /memory/consolidate [post]

func (*MemoryHandler) CreateItem

func (h *MemoryHandler) CreateItem(c *gin.Context)

CreateItem godoc @Summary 新增一条记忆 @Description 手动添加一条长期记忆 @Tags 长期记忆 @Accept json @Produce json @Param request body object true "记忆内容" @Success 200 {object} map[string]interface{} "新增的记忆" @Security Bearer @Router /memory/items [post]

func (*MemoryHandler) DeleteDocument

func (h *MemoryHandler) DeleteDocument(c *gin.Context)

DeleteDocument godoc @Summary 停止用某份文档做个性化检索 @Description 删除一条文档亲和度计数,之后检索不再因为这份文档而加权 @Tags 长期记忆 @Produce json @Param id path string true "亲和度 ID" @Success 200 {object} map[string]interface{} "删除成功" @Security Bearer @Router /memory/documents/{id} [delete]

func (*MemoryHandler) DeleteItem

func (h *MemoryHandler) DeleteItem(c *gin.Context)

DeleteItem godoc @Summary 删除一条记忆 @Description 永久删除一条记忆 @Tags 长期记忆 @Produce json @Param id path string true "记忆ID" @Success 200 {object} map[string]interface{} "删除成功" @Security Bearer @Router /memory/items/{id} [delete]

func (*MemoryHandler) DeleteTopic

func (h *MemoryHandler) DeleteTopic(c *gin.Context)

DeleteTopic godoc @Summary 停止跟踪一个主题 @Description 删除尚未提升的主题计数,并记住这次拒绝,之后不会再自动记为长期关注 @Tags 长期记忆 @Produce json @Param id path string true "主题 ID" @Success 200 {object} map[string]interface{} "删除成功" @Security Bearer @Router /memory/topics/{id} [delete]

func (*MemoryHandler) Export

func (h *MemoryHandler) Export(c *gin.Context)

Export godoc @Summary 导出我的记忆 @Description 以 JSON 导出当前用户的全部记忆 @Tags 长期记忆 @Produce json @Success 200 {object} map[string]interface{} "记忆导出" @Security Bearer @Router /memory/export [get]

func (*MemoryHandler) GetSettings

func (h *MemoryHandler) GetSettings(c *gin.Context)

GetSettings godoc @Summary 获取我的记忆设置 @Description 返回合并后的记忆开关状态(空间级 + 个人级)与记忆条数 @Tags 长期记忆 @Produce json @Success 200 {object} map[string]interface{} "记忆设置" @Security Bearer @Router /memory/settings [get]

func (*MemoryHandler) ListDocuments

func (h *MemoryHandler) ListDocuments(c *gin.Context)

ListDocuments godoc @Summary 列出常用资料 @Description 返回当前用户回答里反复引用的文档,次数未达习惯门槛的不展示 @Tags 长期记忆 @Produce json @Param limit query int false "每页条数" default(50) @Param offset query int false "偏移量" @Success 200 {object} map[string]interface{} "文档列表" @Security Bearer @Router /memory/documents [get]

func (*MemoryHandler) ListItems

func (h *MemoryHandler) ListItems(c *gin.Context)

ListItems godoc @Summary 列出我的记忆 @Description 分页返回当前用户的记忆条目,可按状态过滤 @Tags 长期记忆 @Produce json @Param status query string false "状态过滤" Enums(active, superseded, archived, pending) @Param limit query int false "每页条数" default(50) @Param offset query int false "偏移量" @Success 200 {object} map[string]interface{} "记忆列表" @Security Bearer @Router /memory/items [get]

func (*MemoryHandler) ListTopics

func (h *MemoryHandler) ListTopics(c *gin.Context)

ListTopics godoc @Summary 列出正在观察的主题 @Description 返回已计数、尚未提升为长期关注的主题,以及距离阈值还差几次 @Tags 长期记忆 @Produce json @Param limit query int false "每页条数" default(50) @Param offset query int false "偏移量" @Success 200 {object} map[string]interface{} "主题列表" @Security Bearer @Router /memory/topics [get]

func (*MemoryHandler) PromoteTopic

func (h *MemoryHandler) PromoteTopic(c *gin.Context)

PromoteTopic godoc @Summary 立即记为长期关注 @Description 不等待剩余次数,把正在观察的主题提升为一条长期关注记忆 @Tags 长期记忆 @Produce json @Param id path string true "主题 ID" @Success 200 {object} map[string]interface{} "新增的记忆" @Security Bearer @Router /memory/topics/{id}/promote [post]

func (*MemoryHandler) RejectItem

func (h *MemoryHandler) RejectItem(c *gin.Context)

RejectItem godoc @Summary 否决一条推断出的记忆 @Description 拒绝系统推断的记忆,并记住这次拒绝 @Tags 长期记忆 @Produce json @Param id path string true "记忆 ID" @Success 200 {object} map[string]interface{} "否决成功" @Security Bearer @Router /memory/items/{id}/reject [post]

func (*MemoryHandler) UpdateItem

func (h *MemoryHandler) UpdateItem(c *gin.Context)

UpdateItem godoc @Summary 修改一条记忆 @Description 修改记忆内容与重要度,修改后该条记忆不会被后台抽取覆盖 @Tags 长期记忆 @Accept json @Produce json @Param id path string true "记忆ID" @Param request body object true "记忆内容" @Success 200 {object} map[string]interface{} "更新后的记忆" @Security Bearer @Router /memory/items/{id} [put]

func (*MemoryHandler) UpdateSettings

func (h *MemoryHandler) UpdateSettings(c *gin.Context)

UpdateSettings godoc @Summary 更新我的记忆设置 @Description 开启或关闭当前用户自己的长期记忆 @Tags 长期记忆 @Accept json @Produce json @Param request body object true "设置" @Success 200 {object} map[string]interface{} "更新后的设置" @Security Bearer @Router /memory/settings [put]

type MessageHandler

type MessageHandler struct {
	MessageService interfaces.MessageService // Service that implements message business logic
	// FileService and StorageResolver back the optional `resource_urls=public`
	// mode, which returns loadable HTTP URLs instead of internal
	// `resource://` handles. Both may be nil, in which case only the default
	// handle mode is available.
	FileService     interfaces.FileService
	StorageResolver interfaces.StorageBackendResolver
}

MessageHandler handles HTTP requests related to messages within chat sessions It provides endpoints for loading and managing message history

func NewMessageHandler

func NewMessageHandler(
	messageService interfaces.MessageService,
	fileService interfaces.FileService,
	storageResolver interfaces.StorageBackendResolver,
) *MessageHandler

NewMessageHandler creates a new message handler instance with the required service Parameters:

  • messageService: Service that implements message business logic
  • fileService: Storage access used to sign public resource URLs
  • storageResolver: Resolves per-tenant storage backends for those URLs

Returns a pointer to a new MessageHandler

func (*MessageHandler) DeleteMessage

func (h *MessageHandler) DeleteMessage(c *gin.Context)

DeleteMessage godoc @Summary 删除消息 @Description 从会话中删除指定消息 @Tags 消息 @Accept json @Produce json @Param session_id path string true "会话ID" @Param id path string true "消息ID" @Success 200 {object} map[string]interface{} "删除成功" @Failure 500 {object} errors.AppError "服务器错误" @Security Bearer @Security ApiKeyAuth @Router /messages/{session_id}/{id} [delete]

func (*MessageHandler) GetChatHistoryKBStats

func (h *MessageHandler) GetChatHistoryKBStats(c *gin.Context)

GetChatHistoryKBStats godoc @Summary 获取聊天历史知识库统计 @Description 获取聊天历史知识库的统计信息(已索引消息数、知识库大小等) @Tags 消息 @Accept json @Produce json @Success 200 {object} map[string]interface{} "统计信息" @Security Bearer @Security ApiKeyAuth @Router /messages/chat-history-stats [get]

func (*MessageHandler) LoadMessages

func (h *MessageHandler) LoadMessages(c *gin.Context)

LoadMessages godoc @Summary 加载消息历史 @Description 加载会话的消息历史,支持分页和时间筛选 @Tags 消息 @Accept json @Produce json @Param session_id path string true "会话ID" @Param limit query int false "返回数量" default(20) @Param before_time query string false "在此时间之前的消息(RFC3339Nano格式)" @Param resource_urls query string false "文件引用形式,public 返回可加载直链" Enums(handle, public) default(handle) @Success 200 {object} map[string]interface{} "消息列表" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /messages/{session_id}/load [get]

func (*MessageHandler) SearchMessages

func (h *MessageHandler) SearchMessages(c *gin.Context)

SearchMessages godoc @Summary 搜索历史对话 @Description 通过关键词和/或向量相似度搜索历史对话记录,支持关键词、向量、混合三种模式 @Tags 消息 @Accept json @Produce json @Param request body SearchMessagesRequest true "搜索请求" @Success 200 {object} map[string]interface{} "搜索结果" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /messages/search [post]

type MessageSuggestionHandler

type MessageSuggestionHandler struct {
	// contains filtered or unexported fields
}

func (*MessageSuggestionHandler) Ensure

func (h *MessageSuggestionHandler) Ensure(c *gin.Context)

Ensure godoc @Summary 确保生成回答后推荐问题 @Description 对已完成的助手消息异步生成或重新生成推荐问题;相同配置快照会复用持久化结果 @Tags 会话 @Accept json @Produce json @Param session_id path string true "会话 ID" @Param message_id path string true "助手消息 ID" @Param request body EnsureMessageSuggestionsRequest false "生成选项" @Success 200 {object} map[string]interface{} @Success 202 {object} map[string]interface{} @Security Bearer @Security ApiKeyAuth @Router /sessions/{session_id}/messages/{message_id}/suggestions [post]

func (*MessageSuggestionHandler) Get

Get godoc @Summary 获取回答后推荐问题 @Tags 会话 @Produce json @Param session_id path string true "会话 ID" @Param message_id path string true "助手消息 ID" @Success 200 {object} map[string]interface{} @Security Bearer @Security ApiKeyAuth @Router /sessions/{session_id}/messages/{message_id}/suggestions [get]

func (*MessageSuggestionHandler) RecordEvent

func (h *MessageSuggestionHandler) RecordEvent(c *gin.Context)

RecordEvent godoc @Summary 上报推荐问题事件 @Description 记录曝光、点击或关闭事件 @Tags 会话 @Accept json @Param session_id path string true "会话 ID" @Param request body SuggestionEventRequest true "事件" @Success 204 @Security Bearer @Security ApiKeyAuth @Router /sessions/{session_id}/suggestion-events [post]

type ModelCatalogEntryDTO

type ModelCatalogEntryDTO struct {
	ID              string                `json:"id"`
	Name            string                `json:"name"`
	Type            string                `json:"type"`
	API             api.API               `json:"api,omitempty"`
	Reasoning       bool                  `json:"reasoning"`
	Input           []string              `json:"input,omitempty"`
	ContextWindow   int                   `json:"context_window,omitempty"`
	MaxOutputTokens int                   `json:"max_output_tokens,omitempty"`
	Dimension       int                   `json:"dimension,omitempty"`
	ThinkingLevels  []api.ReasoningEffort `json:"thinking_levels"`
	Cost            *models.ModelCost     `json:"cost,omitempty"`
	// Source is the vendor page these facts were read from, so the editor can
	// send an operator to the documentation for this exact model.
	Source string `json:"source,omitempty"`
}

ModelCatalogEntryDTO is one catalog model for the picker.

type ModelCredentialsHandler

type ModelCredentialsHandler struct {
	// contains filtered or unexported fields
}

ModelCredentialsHandler handles secret credentials for models via the dedicated /models/:id/credentials subresource. See mcp_credentials.go for the rationale; this handler mirrors that contract for Model resources.

Recognized fields: "api_key" (every provider), "app_secret" (WeKnora Cloud).

func NewModelCredentialsHandler

func NewModelCredentialsHandler(svc interfaces.ModelService) *ModelCredentialsHandler

func (*ModelCredentialsHandler) DeleteField

func (h *ModelCredentialsHandler) DeleteField(c *gin.Context)

func (*ModelCredentialsHandler) Put

func (h *ModelCredentialsHandler) Put(c *gin.Context)

type ModelDebugOptions

type ModelDebugOptions struct {
	SystemPrompt string   `json:"system_prompt,omitempty"`
	Temperature  *float64 `json:"temperature,omitempty"`
	TopP         *float64 `json:"top_p,omitempty"`
	MaxTokens    *int     `json:"max_tokens,omitempty"`
	Thinking     *bool    `json:"thinking,omitempty"`
	// ReasoningEffort is the graded level; when set it overrides Thinking.
	ReasoningEffort string `json:"reasoning_effort,omitempty"`
	// Similarity makes an embedding test score the documents (and an
	// optional image) against the input as a search query.
	Similarity bool `json:"similarity,omitempty"`
}

ModelDebugOptions contains the cross-provider parameters exposed by the model debugger. Pointer fields preserve explicit zero/false values.

type ModelHandler

type ModelHandler struct {
	// contains filtered or unexported fields
}

ModelHandler handles HTTP requests for model-related operations It implements the necessary methods to create, retrieve, update, and delete models

func NewModelHandler

func NewModelHandler(service interfaces.ModelService) *ModelHandler

NewModelHandler creates a new instance of ModelHandler It requires a model service implementation that handles business logic Parameters:

  • service: An implementation of the ModelService interface

Returns a pointer to the newly created ModelHandler

func (*ModelHandler) CopyModel

func (h *ModelHandler) CopyModel(c *gin.Context)

CopyModel godoc @Summary 复制模型 @Description 复制模型配置。name 与源模型一致,凭证从已存记录复制,不接受客户端重传。 @Tags 模型管理 @Accept json @Produce json @Param id path string true "源模型ID" @Param request body CopyModelRequest true "副本展示名" @Success 201 {object} map[string]interface{} "复制的模型" @Failure 400 {object} errors.AppError "请求参数错误" @Failure 404 {object} errors.AppError "模型不存在" @Security Bearer @Security ApiKeyAuth @Router /models/{id}/copy [post]

func (*ModelHandler) CreateModel

func (h *ModelHandler) CreateModel(c *gin.Context)

CreateModel godoc @Summary 创建模型 @Description 创建新的模型配置 @Tags 模型管理 @Accept json @Produce json @Param request body CreateModelRequest true "模型信息" @Success 201 {object} map[string]interface{} "创建的模型" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /models [post]

func (*ModelHandler) DebugModel

func (h *ModelHandler) DebugModel(c *gin.Context)

DebugModel executes a saved model through the same service constructors used by production calls and returns the complete normalized response. Credentials stay server-side; the request preview contains only non-secret fields.

func (*ModelHandler) DeleteModel

func (h *ModelHandler) DeleteModel(c *gin.Context)

DeleteModel godoc @Summary 删除模型 @Description 删除指定的模型 @Tags 模型管理 @Accept json @Produce json @Param id path string true "模型ID" @Success 200 {object} map[string]interface{} "删除成功" @Failure 400 {object} errors.AppError "模型仍被知识库、智能体或长期记忆引用" @Failure 404 {object} errors.AppError "模型不存在" @Security Bearer @Security ApiKeyAuth @Router /models/{id} [delete]

func (*ModelHandler) GetModel

func (h *ModelHandler) GetModel(c *gin.Context)

GetModel godoc @Summary 获取模型详情 @Description 根据ID获取模型详情 @Tags 模型管理 @Accept json @Produce json @Param id path string true "模型ID" @Success 200 {object} map[string]interface{} "模型详情" @Failure 404 {object} errors.AppError "模型不存在" @Security Bearer @Security ApiKeyAuth @Router /models/{id} [get]

func (*ModelHandler) ListModelProviders

func (h *ModelHandler) ListModelProviders(c *gin.Context)

ListModelProviders godoc @Summary 获取模型厂商列表 @Description 根据模型类型获取支持的厂商定义(含图标、默认地址、额外字段、内置模型目录与思考能力) @Tags 模型管理 @Accept json @Produce json @Param model_type query string false "模型类型 (chat, embedding, rerank, vllm, asr)" @Success 200 {object} map[string]interface{} "厂商列表" @Security Bearer @Security ApiKeyAuth @Router /models/providers [get]

func (*ModelHandler) ListModels

func (h *ModelHandler) ListModels(c *gin.Context)

ListModels godoc @Summary 获取模型列表 @Description 获取当前空间的所有模型 @Tags 模型管理 @Accept json @Produce json @Success 200 {object} map[string]interface{} "模型列表" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /models [get]

func (*ModelHandler) ResolveModelCatalog

func (h *ModelHandler) ResolveModelCatalog(c *gin.Context)

ResolveModelCatalog godoc @Summary 解析模型的有效接入配置 @Description 根据厂商、模型名、Base URL 与 extra_config 返回目录解析结果(协议、思考等级、上下文等),供模型编辑器实时展示 @Tags 模型管理 @Accept json @Produce json @Param provider query string true "厂商标识" @Param model query string false "模型名" @Param base_url query string false "Base URL" @Param model_type query string false "模型类型" @Success 200 {object} map[string]interface{} "解析结果" @Security Bearer @Security ApiKeyAuth @Router /models/catalog/resolve [get]

func (*ModelHandler) UpdateModel

func (h *ModelHandler) UpdateModel(c *gin.Context)

UpdateModel godoc @Summary 更新模型 @Description 更新模型配置信息 @Tags 模型管理 @Accept json @Produce json @Param id path string true "模型ID" @Param request body UpdateModelRequest true "更新信息" @Success 200 {object} map[string]interface{} "更新后的模型" @Failure 404 {object} errors.AppError "模型不存在" @Security Bearer @Security ApiKeyAuth @Router /models/{id} [put]

type ModelProviderDTO

type ModelProviderDTO struct {
	Value        string            `json:"value"`
	Label        string            `json:"label"`
	Labels       map[string]string `json:"labels,omitempty"`
	Description  string            `json:"description"`
	Descriptions map[string]string `json:"descriptions,omitempty"`
	Website      string            `json:"website,omitempty"`
	// Icon is a data: URI (image/svg+xml;base64) ready for <img src>.
	Icon         string                 `json:"icon,omitempty"`
	API          api.API                `json:"api"`
	Auth         providers.AuthStyle    `json:"auth"`
	RequiresAuth bool                   `json:"requiresAuth"`
	DefaultURLs  map[string]string      `json:"defaultUrls"`
	ModelTypes   []string               `json:"modelTypes"`
	ExtraFields  []providers.ExtraField `json:"extraFields,omitempty"`
	// CredentialLabels rename the primary credential input for the model
	// types that do not take a plain API key (signed rerank APIs).
	CredentialLabels []providers.CredentialLabel `json:"credentialLabels,omitempty"`
	Models           []ModelCatalogEntryDTO      `json:"models,omitempty"`
	Thinking         ProviderThinkingDTO         `json:"thinking"`
	Order            int                         `json:"order"`
}

ModelProviderDTO is the vendor definition the model editor renders from. Everything the UI shows for a vendor (name, icon, URLs, extra fields, catalog models, thinking capabilities) comes from here; the frontend keeps no vendor table of its own.

type ModelTestRequest

type ModelTestRequest struct {
	Spec                      *types.ModelSpecOverride `json:"spec,omitempty"`
	Source                    string                   `json:"source"` // 为空时按需默认为 "remote"
	ModelName                 string                   `json:"modelName" binding:"required"`
	BaseURL                   string                   `json:"baseUrl"`
	APIKey                    string                   `json:"apiKey"`
	Provider                  string                   `json:"provider"`
	InterfaceType             string                   `json:"interfaceType,omitempty"`
	Dimension                 int                      `json:"dimension,omitempty"`
	SupportsDimensionOverride bool                     `json:"supportsDimensionOverride,omitempty"`
	CustomHeaders             map[string]string        `json:"customHeaders,omitempty"`
	ExtraConfig               map[string]string        `json:"extraConfig,omitempty"`
	// AppSecret 用于 LKEAP / Volcengine Rerank 等需要第二段密钥的场景(对应模型 Parameters.AppSecret)。
	AppSecret string `json:"appSecret,omitempty"`
	// ModelID, when set, instructs the handler to substitute any missing
	// secrets (APIKey, AppSecret via ExtraConfig) from the stored model
	// record before assembling the test client. This lets the "Test
	// connection" button work on existing models without making the
	// frontend reload — and ship — the plaintext API key. Other fields
	// (BaseURL, ModelName, etc.) on this request still override the
	// stored values, so a user can validate a new endpoint against the
	// existing credentials in one click.
	ModelID string `json:"modelId,omitempty"`
}

ModelTestRequest 统一的"测试连接"请求体。

四种模型(chat/embedding/rerank/asr)的测试接口共享同一份结构,以便:

  • 前端只需维护一份表单 → 后端映射。
  • 后端可以直接把请求转成 *types.Model,再调用各包的 ConfigFromModel, 与生产路径(service.modelService.GetXxxModel)走完全相同的装配流程, 彻底消除过去每个测试端点手工拼 Config 的样板代码。

所有 provider/model 通用字段都在这里集中声明;若未来新增字段(比如现在的 custom_headers),只需改一处,生产路径和测试路径会同时生效。

type MoveKnowledgeRequest

type MoveKnowledgeRequest struct {
	KnowledgeIDs []string `json:"knowledge_ids" binding:"required,min=1"`
	SourceKBID   string   `json:"source_kb_id"  binding:"required"`
	TargetKBID   string   `json:"target_kb_id"  binding:"required"`
	Mode         string   `json:"mode"          binding:"required,oneof=reuse_vectors reparse"`
}

MoveKnowledgeRequest defines the request for moving knowledge items

type MoveKnowledgeResponse

type MoveKnowledgeResponse struct {
	TaskID         string `json:"task_id"`
	SourceKBID     string `json:"source_kb_id"`
	TargetKBID     string `json:"target_kb_id"`
	KnowledgeCount int    `json:"knowledge_count"`
	Message        string `json:"message"`
}

MoveKnowledgeResponse defines the response for move knowledge

type MoveKnowledgeToFolderRequest

type MoveKnowledgeToFolderRequest struct {
	KBID string   `json:"kb_id" binding:"required"`
	IDs  []string `json:"knowledge_ids" binding:"required"`
	// FolderPath is the destination folder; the empty string is the knowledge
	// base top level. It is deliberately not `binding:"required"` so documents
	// can be moved back out of every folder.
	FolderPath string `json:"folder_path"`
}

MoveKnowledgeToFolderRequest is the body schema for POST /knowledge/folder.

type OrganizationHandler

type OrganizationHandler struct {
	// contains filtered or unexported fields
}

OrganizationHandler implements HTTP request handlers for organization management

func NewOrganizationHandler

func NewOrganizationHandler(
	orgService interfaces.OrganizationService,
	shareService interfaces.KBShareService,
	agentShareService interfaces.AgentShareService,
	customAgentService interfaces.CustomAgentService,
	userService interfaces.UserService,
	tenantService interfaces.TenantService,
	kbService interfaces.KnowledgeBaseService,
	knowledgeRepo interfaces.KnowledgeRepository,
	chunkRepo interfaces.ChunkRepository,
) *OrganizationHandler

NewOrganizationHandler creates a new organization handler

func (*OrganizationHandler) CreateOrganization

func (h *OrganizationHandler) CreateOrganization(c *gin.Context)

CreateOrganization creates a new organization @Summary 创建组织 @Description 创建新的组织,创建者自动成为管理员 @Tags 组织管理 @Accept json @Produce json @Param request body types.CreateOrganizationRequest true "组织信息" @Success 201 {object} map[string]interface{} @Failure 400 {object} apperrors.AppError @Security Bearer @Router /organizations [post]

func (*OrganizationHandler) DeleteOrganization

func (h *OrganizationHandler) DeleteOrganization(c *gin.Context)

DeleteOrganization deletes an organization @Summary 删除组织 @Description 删除组织(仅组织创建者可操作) @Tags 组织管理 @Param id path string true "组织ID" @Success 200 {object} map[string]interface{} @Failure 403 {object} apperrors.AppError @Security Bearer @Router /organizations/{id} [delete]

func (*OrganizationHandler) GenerateInviteCode

func (h *OrganizationHandler) GenerateInviteCode(c *gin.Context)

GenerateInviteCode generates a new invite code @Summary 生成邀请码 @Description 生成新的组织邀请码(需要管理员权限) @Tags 组织管理 @Produce json @Param id path string true "组织ID" @Success 200 {object} map[string]interface{} @Failure 403 {object} apperrors.AppError @Security Bearer @Router /organizations/{id}/invite-code [post]

func (*OrganizationHandler) GetOrganization

func (h *OrganizationHandler) GetOrganization(c *gin.Context)

GetOrganization gets an organization by ID @Summary 获取组织详情 @Description 根据ID获取组织详情 @Tags 组织管理 @Produce json @Param id path string true "组织ID" @Success 200 {object} map[string]interface{} @Failure 404 {object} apperrors.AppError @Security Bearer @Router /organizations/{id} [get]

func (*OrganizationHandler) InviteMember

func (h *OrganizationHandler) InviteMember(c *gin.Context)

InviteMember directly adds a user to organization @Summary 邀请成员 @Description 管理员直接添加用户为组织成员 @Tags 组织管理 @Accept json @Produce json @Param id path string true "组织ID" @Param request body types.InviteMemberRequest true "邀请信息" @Success 200 {object} map[string]interface{} @Failure 400 {object} apperrors.AppError @Failure 403 {object} apperrors.AppError @Security Bearer @Router /organizations/{id}/invite [post]

func (*OrganizationHandler) JoinByInviteCode

func (h *OrganizationHandler) JoinByInviteCode(c *gin.Context)

JoinByInviteCode joins an organization by invite code @Summary 通过邀请码加入组织 @Description 使用邀请码加入组织 @Tags 组织管理 @Accept json @Produce json @Param request body types.JoinOrganizationRequest true "邀请码" @Success 200 {object} map[string]interface{} @Failure 404 {object} apperrors.AppError @Security Bearer @Router /organizations/join [post]

func (*OrganizationHandler) JoinByOrganizationID

func (h *OrganizationHandler) JoinByOrganizationID(c *gin.Context)

JoinByOrganizationID joins a searchable organization by ID (no invite code) @Summary 通过空间 ID 加入(可搜索空间) @Description 加入已开放可被搜索的空间,无需邀请码 @Tags 组织管理 @Accept json @Produce json @Param request body types.JoinByOrganizationIDRequest true "空间 ID" @Success 200 {object} map[string]interface{} @Failure 403 {object} apperrors.AppError @Security Bearer @Router /organizations/join-by-id [post]

func (*OrganizationHandler) LeaveOrganization

func (h *OrganizationHandler) LeaveOrganization(c *gin.Context)

LeaveOrganization allows a user to leave an organization @Summary 退出组织 @Description 退出指定组织 @Tags 组织管理 @Param id path string true "组织ID" @Success 200 {object} map[string]interface{} @Failure 403 {object} apperrors.AppError @Security Bearer @Router /organizations/{id}/leave [post]

func (*OrganizationHandler) ListAgentShares

func (h *OrganizationHandler) ListAgentShares(c *gin.Context)

ListAgentShares lists all shares for an agent

func (*OrganizationHandler) ListJoinRequests

func (h *OrganizationHandler) ListJoinRequests(c *gin.Context)

ListJoinRequests lists pending join requests for an organization (admin only) @Summary 获取待审核加入申请列表 @Description 获取组织的待审核加入申请(仅管理员) @Tags 组织管理 @Produce json @Param id path string true "组织ID" @Success 200 {object} map[string]interface{} @Failure 403 {object} apperrors.AppError @Security Bearer @Router /organizations/{id}/join-requests [get]

func (*OrganizationHandler) ListKBShares

func (h *OrganizationHandler) ListKBShares(c *gin.Context)

ListKBShares lists all shares for a knowledge base @Summary 获取知识库的共享列表 @Description 获取知识库的所有共享记录 @Tags 知识库共享 @Produce json @Param id path string true "知识库ID" @Success 200 {object} types.ListSharesResponse @Security Bearer @Router /knowledge-bases/{id}/shares [get]

func (*OrganizationHandler) ListMembers

func (h *OrganizationHandler) ListMembers(c *gin.Context)

ListMembers lists all tenant-members of an organization @Summary 获取组织成员列表 @Description 获取组织的所有成员(按空间) @Tags 组织管理 @Produce json @Param id path string true "组织ID" @Success 200 {object} types.ListMembersResponse @Security Bearer @Router /organizations/{id}/members [get]

func (*OrganizationHandler) ListMyOrganizations

func (h *OrganizationHandler) ListMyOrganizations(c *gin.Context)

ListMyOrganizations lists organizations that the current tenant belongs to. Response includes resource_counts (per-org KB/agent counts) for list sidebar so frontend does not need a separate GET /me/resource-counts. @Summary 获取我的组织列表 @Description 获取当前空间所属的所有组织,并附带各空间内知识库/智能体数量 @Tags 组织管理 @Produce json @Success 200 {object} types.ListOrganizationsResponse @Security Bearer @Router /organizations [get]

func (*OrganizationHandler) ListOrgAgentShares

func (h *OrganizationHandler) ListOrgAgentShares(c *gin.Context)

ListOrgAgentShares lists all agents shared to an organization.

ListOrgAgentShares godoc @Summary 获取共享到本组织的智能体 @Description 返回所有被共享到指定组织的智能体(含我的有效权限) @Tags 组织 @Produce json @Param id path string true "组织 ID" @Success 200 {object} map[string]interface{} "智能体共享列表 + total" @Failure 403 {object} apperrors.AppError "非组织成员" @Security Bearer @Security ApiKeyAuth @Router /organizations/{id}/agent-shares [get]

func (*OrganizationHandler) ListOrgShares

func (h *OrganizationHandler) ListOrgShares(c *gin.Context)

ListOrgShares lists all knowledge bases shared to a specific organization @Summary 获取组织的共享知识库列表 @Description 获取共享到指定组织的所有知识库 @Tags 组织管理 @Produce json @Param id path string true "组织ID" @Success 200 {object} types.ListSharesResponse @Security Bearer @Router /organizations/{id}/shares [get]

func (*OrganizationHandler) ListOrganizationSharedAgents

func (h *OrganizationHandler) ListOrganizationSharedAgents(c *gin.Context)

ListOrganizationSharedAgents lists all agents in the given organization (including those shared by the current tenant), for the list page when a space is selected. @Summary 获取空间内全部智能体(含我共享的) @Description 获取指定空间下所有共享智能体,包含他人共享的与我共享的,用于列表页空间视角 @Tags 组织管理 @Produce json @Param id path string true "组织ID" @Success 200 {object} map[string]interface{} @Security Bearer @Router /organizations/{id}/shared-agents [get]

func (*OrganizationHandler) ListOrganizationSharedKnowledgeBases

func (h *OrganizationHandler) ListOrganizationSharedKnowledgeBases(c *gin.Context)

ListOrganizationSharedKnowledgeBases lists all knowledge bases in the given organization (including those shared by the current tenant and those from shared agents), for the list page when a space is selected. @Summary 获取空间内全部知识库(含我共享的、含智能体携带的) @Description 获取指定空间下所有共享知识库,包含直接共享的与通过共享智能体可见的,用于列表页空间视角 @Tags 组织管理 @Produce json @Param id path string true "组织ID" @Success 200 {object} map[string]interface{} @Security Bearer @Router /organizations/{id}/shared-knowledge-bases [get]

func (*OrganizationHandler) ListSharedAgents

func (h *OrganizationHandler) ListSharedAgents(c *gin.Context)

ListSharedAgents lists agents shared to the current user.

ListSharedAgents godoc @Summary 获取我可访问的共享智能体 @Description 返回所有共享给当前用户所在组织的智能体 @Tags 组织 @Produce json @Success 200 {object} map[string]interface{} "智能体列表 + total" @Failure 500 {object} apperrors.AppError "服务器错误" @Security Bearer @Security ApiKeyAuth @Router /shared-agents [get]

func (*OrganizationHandler) ListSharedKnowledgeBases

func (h *OrganizationHandler) ListSharedKnowledgeBases(c *gin.Context)

ListSharedKnowledgeBases lists all knowledge bases shared to the current user @Summary 获取共享给我的知识库列表 @Description 获取通过组织共享给当前用户的所有知识库 @Tags 知识库共享 @Produce json @Success 200 {object} map[string]interface{} @Security Bearer @Router /shared-knowledge-bases [get]

func (*OrganizationHandler) PreviewByInviteCode

func (h *OrganizationHandler) PreviewByInviteCode(c *gin.Context)

PreviewByInviteCode previews organization info by invite code (without joining) @Summary 通过邀请码预览组织 @Description 通过邀请码获取组织基本信息(不加入) @Tags 组织管理 @Produce json @Param code path string true "邀请码" @Success 200 {object} map[string]interface{} @Failure 404 {object} apperrors.AppError @Security Bearer @Router /organizations/preview/{code} [get]

func (*OrganizationHandler) RemoveAgentShare

func (h *OrganizationHandler) RemoveAgentShare(c *gin.Context)

RemoveAgentShare removes an agent share.

RemoveAgentShare godoc @Summary 取消智能体共享 @Description 从智能体的共享列表中移除指定共享关系 @Tags 组织 @Produce json @Param id path string true "智能体 ID" @Param share_id path string true "共享记录 ID" @Success 200 {object} map[string]interface{} "success: true" @Failure 403 {object} apperrors.AppError "无权限" @Security Bearer @Security ApiKeyAuth @Router /agents/{id}/shares/{share_id} [delete]

func (*OrganizationHandler) RemoveMember

func (h *OrganizationHandler) RemoveMember(c *gin.Context)

RemoveMember removes a tenant-member from an organization @Summary 移除成员 @Description 从组织中移除成员空间(需要管理员权限) @Tags 组织管理 @Param id path string true "组织ID" @Param tenant_id path string true "成员空间ID" @Success 200 {object} map[string]interface{} @Failure 403 {object} apperrors.AppError @Security Bearer @Router /organizations/{id}/members/{tenant_id} [delete]

func (*OrganizationHandler) RemoveShare

func (h *OrganizationHandler) RemoveShare(c *gin.Context)

RemoveShare removes a share @Summary 取消共享 @Description 取消知识库的共享 @Tags 知识库共享 @Param id path string true "知识库ID" @Param share_id path string true "共享记录ID" @Success 200 {object} map[string]interface{} @Failure 403 {object} apperrors.AppError @Security Bearer @Router /knowledge-bases/{id}/shares/{share_id} [delete]

func (*OrganizationHandler) RequestRoleUpgrade

func (h *OrganizationHandler) RequestRoleUpgrade(c *gin.Context)

RequestRoleUpgrade submits a request to upgrade role in an organization @Summary 申请权限升级 @Description 现有成员申请更高权限 @Tags 组织管理 @Accept json @Produce json @Param id path string true "组织ID" @Param request body types.RequestRoleUpgradeRequest true "申请信息" @Success 200 {object} map[string]interface{} @Failure 400 {object} apperrors.AppError @Security Bearer @Router /organizations/{id}/request-upgrade [post]

func (*OrganizationHandler) ReviewJoinRequest

func (h *OrganizationHandler) ReviewJoinRequest(c *gin.Context)

ReviewJoinRequest approves or rejects a join request (admin only) @Summary 审核加入申请 @Description 通过或拒绝加入申请(仅管理员) @Tags 组织管理 @Accept json @Produce json @Param id path string true "组织ID" @Param request_id path string true "申请ID" @Param request body types.ReviewJoinRequestRequest true "审核结果" @Success 200 {object} map[string]interface{} @Failure 403 {object} apperrors.AppError @Security Bearer @Router /organizations/{id}/join-requests/{request_id}/review [put]

func (*OrganizationHandler) SearchOrganizations

func (h *OrganizationHandler) SearchOrganizations(c *gin.Context)

SearchOrganizations returns searchable (discoverable) organizations @Summary 搜索可加入的空间 @Description 搜索已开放可被搜索的空间,用于发现并加入 @Tags 组织管理 @Produce json @Param q query string false "搜索关键词(空间名称或描述)" @Param limit query int false "返回数量限制" default(20) @Success 200 {object} map[string]interface{} @Security Bearer @Router /organizations/search [get]

func (*OrganizationHandler) SearchTenantsForInvite

func (h *OrganizationHandler) SearchTenantsForInvite(c *gin.Context)

SearchTenantsForInvite resolves one exact workspace ID for an organization administrator. Workspace names are never searched across tenants. @Summary Resolve a workspace ID for invitation @Tags 组织管理 @Produce json @Param id path string true "组织ID" @Param q query string true "Exact workspace ID" @Success 200 {object} map[string]interface{} @Security Bearer @Router /organizations/{id}/search-tenants [get]

func (*OrganizationHandler) SearchUsersForInvite

func (h *OrganizationHandler) SearchUsersForInvite(c *gin.Context)

SearchUsersForInvite is retained as a thin compatibility shim that delegates to SearchTenantsForInvite, so older frontends still get tenant-grouped results without breaking the call site. The response shape here is (intentionally) the new tenant-candidate shape; the previous shape returned one row per matching user, which leaked the pre-Plan-3 mental model.

@Deprecated Use SearchTenantsForInvite. Kept for one release. @Router /organizations/{id}/search-users [get]

func (*OrganizationHandler) SetSharedAgentDisabledByMe

func (h *OrganizationHandler) SetSharedAgentDisabledByMe(c *gin.Context)

SetSharedAgentDisabledByMe sets whether the current tenant has disabled this shared agent for their conversation dropdown

func (*OrganizationHandler) ShareAgent

func (h *OrganizationHandler) ShareAgent(c *gin.Context)

ShareAgent shares an agent to an organization

func (*OrganizationHandler) ShareKnowledgeBase

func (h *OrganizationHandler) ShareKnowledgeBase(c *gin.Context)

ShareKnowledgeBase shares a knowledge base to an organization @Summary 共享知识库到组织 @Description 将知识库共享到指定组织 @Tags 知识库共享 @Accept json @Produce json @Param id path string true "知识库ID" @Param request body types.ShareKnowledgeBaseRequest true "共享信息" @Success 201 {object} map[string]interface{} @Failure 403 {object} apperrors.AppError @Security Bearer @Router /knowledge-bases/{id}/shares [post]

func (*OrganizationHandler) SubmitJoinRequest

func (h *OrganizationHandler) SubmitJoinRequest(c *gin.Context)

SubmitJoinRequest submits a join request for organizations that require approval @Summary 提交加入申请 @Description 对需要审核的组织提交加入申请 @Tags 组织管理 @Accept json @Produce json @Param request body types.SubmitJoinRequestRequest true "申请信息" @Success 200 {object} map[string]interface{} @Failure 400 {object} apperrors.AppError @Security Bearer @Router /organizations/join-request [post]

func (*OrganizationHandler) UpdateMemberRole

func (h *OrganizationHandler) UpdateMemberRole(c *gin.Context)

UpdateMemberRole updates a tenant-member's role @Summary 更新成员角色 @Description 更新组织成员(空间)的角色(需要管理员权限) @Tags 组织管理 @Accept json @Produce json @Param id path string true "组织ID" @Param tenant_id path string true "成员空间ID" @Param request body types.UpdateMemberRoleRequest true "角色信息" @Success 200 {object} map[string]interface{} @Failure 403 {object} apperrors.AppError @Security Bearer @Router /organizations/{id}/members/{tenant_id} [put]

func (*OrganizationHandler) UpdateOrganization

func (h *OrganizationHandler) UpdateOrganization(c *gin.Context)

UpdateOrganization updates an organization @Summary 更新组织 @Description 更新组织信息(需要管理员权限) @Tags 组织管理 @Accept json @Produce json @Param id path string true "组织ID" @Param request body types.UpdateOrganizationRequest true "更新信息" @Success 200 {object} map[string]interface{} @Failure 403 {object} apperrors.AppError @Security Bearer @Router /organizations/{id} [put]

func (*OrganizationHandler) UpdateSharePermission

func (h *OrganizationHandler) UpdateSharePermission(c *gin.Context)

UpdateSharePermission updates the permission of a share @Summary 更新共享权限 @Description 更新知识库共享的权限级别 @Tags 知识库共享 @Accept json @Produce json @Param id path string true "知识库ID" @Param share_id path string true "共享记录ID" @Param request body types.UpdateSharePermissionRequest true "权限信息" @Success 200 {object} map[string]interface{} @Failure 403 {object} apperrors.AppError @Security Bearer @Router /knowledge-bases/{id}/shares/{share_id} [put]

type PreviewChunkResult

type PreviewChunkResult struct {
	Seq              int    `json:"seq"`
	Start            int    `json:"start"`
	End              int    `json:"end"`
	SizeChars        int    `json:"size_chars"`
	SizeTokensApprox int    `json:"size_tokens_approx"`
	ContextHeader    string `json:"context_header,omitempty"`
	Content          string `json:"content"`
}

PreviewChunkResult describes one chunk emitted during preview.

type PreviewChunkingPayload

type PreviewChunkingPayload struct {
	ChunkSize         int      `json:"chunk_size"`
	ChunkOverlap      int      `json:"chunk_overlap"`
	Separators        []string `json:"separators"`
	EnableParentChild bool     `json:"enable_parent_child"`
	ParentChunkSize   int      `json:"parent_chunk_size"`
	ChildChunkSize    int      `json:"child_chunk_size"`
	Strategy          string   `json:"strategy"`
	TokenLimit        int      `json:"token_limit"`
	Languages         []string `json:"languages"`
}

PreviewChunkingPayload mirrors the snake_case JSON the rest of the API uses for ChunkingConfig fields. We don't reuse types.ChunkingConfig directly because it carries unrelated parser rules and table-processing metadata that the preview path does not use.

type PreviewChunkingRequest

type PreviewChunkingRequest struct {
	Text           string                 `json:"text"`
	ChunkingConfig PreviewChunkingPayload `json:"chunking_config"`
}

PreviewChunkingRequest is the body shape accepted by /chunker/preview. Text is checked manually below so we can return a friendlier error than gin's default "Field validation for 'Text' failed on the 'required' tag".

type PreviewChunkingResponse

type PreviewChunkingResponse struct {
	SelectedTier chunker.StrategyTier    `json:"selected_tier"`
	TierChain    []chunker.StrategyTier  `json:"tier_chain"`
	Rejected     []chunker.TierRejection `json:"rejected"`
	Profile      *chunker.DocProfile     `json:"profile"`
	Chunks       []PreviewChunkResult    `json:"chunks"`
	Stats        PreviewChunkingStats    `json:"stats"`
}

PreviewChunkingResponse is the body returned by /chunker/preview.

type PreviewChunkingStats

type PreviewChunkingStats struct {
	Count       int `json:"count"`
	AvgChars    int `json:"avg_chars"`
	MinChars    int `json:"min_chars"`
	MaxChars    int `json:"max_chars"`
	StddevChars int `json:"stddev_chars"`
	// TruncatedTo, when set, is the original chunk count before the
	// response was truncated to previewMaxChunks for transport.
	TruncatedTo int `json:"truncated_to,omitempty"`
}

PreviewChunkingStats summarizes chunk-size distribution. Computed over the FULL chunk set, even when the response truncates to previewMaxChunks items, so avg/min/max/stddev reflect the real distribution, not just the first N.

type PromoteUserToSystemAdminRequest

type PromoteUserToSystemAdminRequest struct {
	UserID string `json:"user_id"`
	Email  string `json:"email"`
}

PromoteUserToSystemAdminRequest defines the request for promoting a user to system admin.

Either user_id (UUID) or email must be supplied. When both are present user_id wins — explicit IDs are unambiguous, an email collision (extremely rare in practice but possible during a tenant merge) would otherwise silently target the wrong row.

We don't expose a `binding:"required"` tag on either field because gin's validator can't express the OR constraint; the handler does the check manually and returns 400 with a specific message for each branch.

type ProviderThinkingDTO

type ProviderThinkingDTO struct {
	Format string                `json:"format"`
	Levels []api.ReasoningEffort `json:"levels"`
}

ProviderThinkingDTO summarizes how the vendor encodes thinking so the UI can explain the reasoning selector.

type RemoteModelCheckRequest deprecated

type RemoteModelCheckRequest = ModelTestRequest

RemoteModelCheckRequest 兼容旧 swagger 定义。

Deprecated: 保留是为了不破坏已生成的 API 文档,新代码请直接使用 ModelTestRequest。

type RenameKnowledgeFolderRequest

type RenameKnowledgeFolderRequest struct {
	From string `json:"from" binding:"required"`
	To   string `json:"to"   binding:"required"`
}

RenameKnowledgeFolderRequest is the body schema for PUT /knowledge-bases/:id/knowledge/folders.

type ResetUserPasswordRequest

type ResetUserPasswordRequest struct {
	Email       string `json:"email" binding:"required,email"`
	NewPassword string `json:"new_password" binding:"required"`
}

ResetUserPasswordRequest defines the system-administrator password-reset payload. Email is intentionally the only user-facing identifier: the UI is an operator tool and emails are easier to verify than UUIDs. The password is never written to logs or audit details.

type RevertChunkRequest

type RevertChunkRequest struct {
	Revision         *int `json:"revision" binding:"required"`
	ExpectedRevision *int `json:"expected_revision"`
}

type RevokeSystemAdminRequest

type RevokeSystemAdminRequest struct {
	UserID string `json:"user_id" binding:"required"`
}

RevokeSystemAdminRequest defines the request for revoking system admin privileges

type RuntimeQueuesResponse

type RuntimeQueuesResponse struct {
	Available             bool                       `json:"available"`
	UpstreamConcurrency   int                        `json:"upstream_concurrency"`
	ParseConcurrency      int                        `json:"parse_concurrency"` // compatibility alias for upstream_concurrency
	WikiConcurrency       int                        `json:"wiki_concurrency"`  // compatibility field
	Pools                 []RuntimeWorkerPool        `json:"pools"`
	Queues                []types.QueueStat          `json:"queues"`
	ModelLimiterAvailable bool                       `json:"model_limiter_available"`
	Models                []modellimiter.RuntimeStat `json:"models"`
	Timestamp             int64                      `json:"timestamp"`
}

type RuntimeTasksResponse

type RuntimeTasksResponse struct {
	Available  bool                    `json:"available"`
	Tasks      []types.RuntimeTaskInfo `json:"tasks"`
	PageSize   int                     `json:"page_size"`
	HasMore    bool                    `json:"has_more"`
	NextCursor string                  `json:"next_cursor,omitempty"`
}

type RuntimeWorkerPool

type RuntimeWorkerPool struct {
	Name            string  `json:"name"`
	Concurrency     int     `json:"concurrency"` // configured per instance
	QueueCount      int     `json:"queue_count"`
	Instances       int     `json:"instances"`        // live asynq server heartbeats
	ClusterCapacity int     `json:"cluster_capacity"` // sum of live server concurrency
	Active          int     `json:"active"`           // live workers assigned to this pool
	Utilization     float64 `json:"utilization"`      // Active / ClusterCapacity
}

ListSystemSettings godoc @Summary List all system settings @Description Return every row in the system_settings table (system-scope, @Description not workspace-scoped). SystemAdmin only. @Tags System Admin @Produce json @Success 200 {array} types.SystemSetting "list of settings" @Failure 403 {object} map[string]interface{} "Forbidden: not a system admin" @Router /system/admin/settings [get] RuntimeQueuesResponse is the payload for the SystemAdmin runtime queue dashboard. `available` is false in Lite mode (no Redis/asynq) so the UI can render an "unavailable in this deployment" state instead of an empty table. Each pool reports configured per-process concurrency plus live cluster capacity/active workers aggregated from asynq server heartbeats.

type SandboxCheckItem

type SandboxCheckItem struct {
	Name string `json:"name"`
	OK   *bool  `json:"ok"`
	// Message carries free-form provider detail for an executed probe.
	Message string `json:"message,omitempty"`
	// Reason is a stable code explaining why a probe was skipped. It exists so
	// the UI can phrase the skip in the operator's language instead of echoing
	// a server-side sentence.
	Reason    string `json:"reason,omitempty"`
	LatencyMS int64  `json:"latency_ms,omitempty"`
}

SandboxCheckItem is one probe outcome. OK is nil when the probe was not executed, which distinguishes "skipped" from "failed" in the UI.

type SandboxCheckRequest

type SandboxCheckRequest struct {
	Config *types.TenantSandboxConfig `json:"config"`
	// ConfigID lets an edit form test stored credentials while overriding only
	// the fields the admin changed in the drawer.
	ConfigID string `json:"config_id"`
	// Deep additionally runs a throwaway script. For remote backends this also
	// creates and destroys one sandbox, which is the only way to validate the
	// template ID, data plane, in-sandbox execution, and outbound egress. It may
	// consume real sandbox time, so it is opt-in.
	Deep bool `json:"deep"`
}

SandboxCheckRequest is the body for POST /system/sandbox-check. Secrets may arrive redacted; they are resolved against the workspace's stored config so an admin can test without retyping an API key.

type SandboxCheckResponse

type SandboxCheckResponse struct {
	OK           bool               `json:"ok"`
	Provider     string             `json:"provider"`
	Checks       []SandboxCheckItem `json:"checks"`
	Capabilities map[string]bool    `json:"capabilities,omitempty"`
}

SandboxCheckResponse aggregates the probes for one sandbox configuration.

type SandboxConfigHandler

type SandboxConfigHandler struct {
	// contains filtered or unexported fields
}

func (*SandboxConfigHandler) Create

func (h *SandboxConfigHandler) Create(c *gin.Context)

Create godoc @Summary Create sandbox config @Description Create a named workspace sandbox backend config. Credentials are masked in the response. @Tags SandboxConfig @Accept json @Produce json @Param request body sandboxConfigRequest true "Sandbox backend config" @Success 201 {object} map[string]interface{} "Created sandbox config" @Failure 400 {object} apperrors.AppError "Invalid request or validation failure" @Failure 401 {object} map[string]interface{} "Unauthorized" @Security Bearer @Security ApiKeyAuth @Router /sandbox-configs [post]

func (*SandboxConfigHandler) Delete

func (h *SandboxConfigHandler) Delete(c *gin.Context)

Delete godoc @Summary Delete sandbox config @Description Soft-delete a sandbox backend config. force=true only overrides unverifiable provider inventory, never confirmed live sandboxes. @Tags SandboxConfig @Produce json @Param id path string true "Sandbox config ID" @Param force query bool false "Force delete when inventory is unverifiable" @Success 200 {object} map[string]interface{} "Deletion success" @Failure 401 {object} map[string]interface{} "Unauthorized" @Failure 409 {object} map[string]interface{} "Live sandboxes or unverifiable inventory" @Security Bearer @Security ApiKeyAuth @Router /sandbox-configs/{id} [delete]

func (*SandboxConfigHandler) Get

func (h *SandboxConfigHandler) Get(c *gin.Context)

Get godoc @Summary Get sandbox config @Description Retrieve a workspace sandbox backend config with credentials masked. @Tags SandboxConfig @Produce json @Param id path string true "Sandbox config ID" @Success 200 {object} map[string]interface{} "Sandbox config" @Failure 401 {object} map[string]interface{} "Unauthorized" @Failure 404 {object} apperrors.AppError "Sandbox config not found" @Security Bearer @Security ApiKeyAuth @Router /sandbox-configs/{id} [get]

func (*SandboxConfigHandler) Inventory

func (h *SandboxConfigHandler) Inventory(c *gin.Context)

Inventory godoc @Summary Inspect sandbox config inventory @Description Return live/paused sandbox inventory and affected agent names for one config. @Tags SandboxConfig @Produce json @Param id path string true "Sandbox config ID" @Success 200 {object} map[string]interface{} "Sandbox inventory" @Failure 401 {object} map[string]interface{} "Unauthorized" @Security Bearer @Security ApiKeyAuth @Router /sandbox-configs/{id}/sandboxes [get]

func (*SandboxConfigHandler) List

func (h *SandboxConfigHandler) List(c *gin.Context)

List godoc @Summary List sandbox configs @Description List workspace sandbox backend configs with credentials masked. @Tags SandboxConfig @Produce json @Success 200 {object} map[string]interface{} "Sandbox configs and defaults" @Failure 401 {object} map[string]interface{} "Unauthorized" @Security Bearer @Security ApiKeyAuth @Router /sandbox-configs [get]

func (*SandboxConfigHandler) QueryTemplates

func (h *SandboxConfigHandler) QueryTemplates(c *gin.Context)

QueryTemplates returns the templates visible through an unsaved workspace connection. ensure_standard / ensure_desktop start a build only when that WeKnora template is missing (from the published Hub image); replace_standard / replace_desktop rebuild it so a new spec (DNS, image) can take effect. Replace requires config_id.

func (*SandboxConfigHandler) SetWorkspacePolicy

func (h *SandboxConfigHandler) SetWorkspacePolicy(c *gin.Context)

SetWorkspacePolicy toggles script execution for the whole workspace. It stays open on Lite: the host sandbox honours the same switch.

func (*SandboxConfigHandler) Update

func (h *SandboxConfigHandler) Update(c *gin.Context)

Update godoc @Summary Update sandbox config @Description Update a sandbox backend config. Identity-field changes are refused while the config owns live or paused sandboxes. @Tags SandboxConfig @Accept json @Produce json @Param id path string true "Sandbox config ID" @Param request body sandboxConfigRequest true "Updated sandbox config" @Success 200 {object} map[string]interface{} "Updated sandbox config" @Failure 400 {object} apperrors.AppError "Invalid request or validation failure" @Failure 401 {object} map[string]interface{} "Unauthorized" @Failure 404 {object} apperrors.AppError "Sandbox config not found" @Failure 409 {object} map[string]interface{} "Live sandboxes or unverifiable inventory" @Failure 423 {object} map[string]interface{} "Sandbox config is being modified by another request" @Security Bearer @Security ApiKeyAuth @Router /sandbox-configs/{id} [put]

type SandboxSkillHandler

type SandboxSkillHandler struct {
	// contains filtered or unexported fields
}

SandboxSkillHandler serves the agent-skill endpoints of one sandbox config.

func NewSandboxSkillHandler

func NewSandboxSkillHandler(
	svc sandboxSkillService, streams interfaces.StreamManager,
) *SandboxSkillHandler

NewSandboxSkillHandler constructs the admin HTTP surface for tenant skills.

func (*SandboxSkillHandler) Delete

func (h *SandboxSkillHandler) Delete(c *gin.Context)

Delete godoc @Summary Remove an installed skill @Description Remove a skill from the config's image. The removal rebuilds @Description the image and runs for minutes, so it is only accepted; follow @Description it via the install-events stream. @Tags SandboxConfig @Produce json @Param id path string true "Sandbox config ID" @Param skillId path string true "Skill ID" @Success 202 {object} map[string]interface{} "Removal accepted" @Failure 401 {object} map[string]interface{} "Unauthorized" @Failure 404 {object} apperrors.AppError "Skill not found" @Security Bearer @Security ApiKeyAuth @Router /sandbox-configs/{id}/skills/{skillId} [delete]

func (*SandboxSkillHandler) Get

func (h *SandboxSkillHandler) Get(c *gin.Context)

Get godoc @Summary Get an installed skill @Description Retrieve one installed skill of a sandbox config. @Tags SandboxConfig @Produce json @Param id path string true "Sandbox config ID" @Param skillId path string true "Skill ID" @Success 200 {object} map[string]interface{} "Installed skill" @Failure 401 {object} map[string]interface{} "Unauthorized" @Failure 404 {object} apperrors.AppError "Skill not found" @Security Bearer @Security ApiKeyAuth @Router /sandbox-configs/{id}/skills/{skillId} [get]

func (*SandboxSkillHandler) GetFile

func (h *SandboxSkillHandler) GetFile(c *gin.Context)

GetFile godoc @Summary Read one file of an installed skill @Description Read one skill file as UTF-8, a small base64 image, or binary. @Tags SandboxConfig @Produce json @Param id path string true "Sandbox config ID" @Param skillId path string true "Skill ID" @Param path query string true "Skill-root-relative file path" @Success 200 {object} map[string]interface{} "Skill file" @Failure 400 {object} apperrors.AppError "Invalid path" @Failure 401 {object} map[string]interface{} "Unauthorized" @Failure 404 {object} apperrors.AppError "Skill or file not found" @Security Bearer @Security ApiKeyAuth @Router /sandbox-configs/{id}/skills/{skillId}/files/content [get]

func (*SandboxSkillHandler) InstallEvents

func (h *SandboxSkillHandler) InstallEvents(c *gin.Context)

InstallEvents godoc @Summary Follow an install or removal @Description Server-sent progress for one install or removal. The stream @Description always terminates: with the run's own terminal event, with one @Description derived from the durable status, or with a "detached" frame @Description when it stops following a run that is still going. @Tags SandboxConfig @Produce text/event-stream @Param id path string true "Sandbox config ID" @Param skillId path string true "Skill ID" @Success 200 {string} string "SSE stream of progress events" @Failure 401 {object} map[string]interface{} "Unauthorized" @Failure 404 {object} apperrors.AppError "Skill not found" @Security Bearer @Security ApiKeyAuth @Router /sandbox-configs/{id}/skills/{skillId}/install-events [get]

func (*SandboxSkillHandler) InstallGuidance

func (h *SandboxSkillHandler) InstallGuidance(c *gin.Context)

InstallGuidance exposes only the guidance for this tenant/config/skill's current run.

func (*SandboxSkillHandler) InstallTranscript

func (h *SandboxSkillHandler) InstallTranscript(c *gin.Context)

InstallTranscript godoc @Summary Follow an install's agent transcript @Description Server-sent replay of everything the installer agent did — the @Description prompt it was given, its thinking, the commands it ran and @Description their output — followed live while the install is still @Description running. Frames are the same shape the chat stream uses, so a @Description console renders an install with the components it renders a @Description chat turn with. 404 once the event log has expired; the @Description durable message history is the fallback. @Tags SandboxConfig @Produce text/event-stream @Param id path string true "Sandbox config ID" @Param skillId path string true "Skill ID" @Success 200 {string} string "SSE stream of transcript events" @Success 204 {string} string "Install is still preparing; retry once locators exist" @Failure 401 {object} map[string]interface{} "Unauthorized" @Failure 404 {object} apperrors.AppError "Skill or transcript not found" @Security Bearer @Security ApiKeyAuth @Router /sandbox-configs/{id}/skills/{skillId}/transcript [get]

The transcript deliberately does not reuse /sessions/continue-stream. That endpoint authorizes by "does this chat session belong to you", while an install is a workspace-level maintenance run whose session is hidden from the session list on purpose — the two rules pull in opposite directions. Here the skill lookup above is the authorization, exactly as it is for every other route in this file.

func (*SandboxSkillHandler) List

func (h *SandboxSkillHandler) List(c *gin.Context)

List godoc @Summary List installed skills @Description List the agent skills installed onto one sandbox config's image. @Tags SandboxConfig @Produce json @Param id path string true "Sandbox config ID" @Success 200 {object} map[string]interface{} "Installed skills" @Failure 401 {object} map[string]interface{} "Unauthorized" @Failure 404 {object} apperrors.AppError "Sandbox config not found" @Security Bearer @Security ApiKeyAuth @Router /sandbox-configs/{id}/skills [get]

func (*SandboxSkillHandler) ListFiles

func (h *SandboxSkillHandler) ListFiles(c *gin.Context)

ListFiles godoc @Summary List files of an installed skill @Description List files in the stored skill bundle without starting a sandbox. @Tags SandboxConfig @Produce json @Param id path string true "Sandbox config ID" @Param skillId path string true "Skill ID" @Success 200 {object} map[string]interface{} "Skill files" @Failure 401 {object} map[string]interface{} "Unauthorized" @Failure 404 {object} apperrors.AppError "Skill or files not found" @Security Bearer @Security ApiKeyAuth @Router /sandbox-configs/{id}/skills/{skillId}/files [get]

func (*SandboxSkillHandler) Patch

func (h *SandboxSkillHandler) Patch(c *gin.Context)

Patch godoc @Summary Update an installed skill @Description Show or hide an installed skill and set the workspace-wide values of the environment variables it declared. Either field may be sent, or both. The files stay in the image either way; removal is a separate flow. @Tags SandboxConfig @Accept json @Produce json @Param id path string true "Sandbox config ID" @Param skillId path string true "Skill ID" @Param request body skillPatchRequest true "Fields to update" @Success 200 {object} map[string]interface{} "Updated skill" @Failure 400 {object} apperrors.AppError "Invalid request" @Failure 401 {object} map[string]interface{} "Unauthorized" @Failure 404 {object} apperrors.AppError "Skill not found" @Security Bearer @Security ApiKeyAuth @Router /sandbox-configs/{id}/skills/{skillId} [patch]

func (*SandboxSkillHandler) Reinstall

func (h *SandboxSkillHandler) Reinstall(c *gin.Context)

Reinstall godoc @Summary Retry a skill install @Description Retry a failed install from the stored archive; does not re-upload. @Tags SandboxConfig @Produce json @Param id path string true "Sandbox config ID" @Param skillId path string true "Skill ID" @Success 202 {object} map[string]interface{} "Reinstall accepted" @Failure 400 {object} apperrors.AppError "The stored archive is gone" @Failure 401 {object} map[string]interface{} "Unauthorized" @Failure 404 {object} apperrors.AppError "Skill not found" @Security Bearer @Security ApiKeyAuth @Router /sandbox-configs/{id}/skills/{skillId}/reinstall [post]

func (*SandboxSkillHandler) SteerInstall

func (h *SandboxSkillHandler) SteerInstall(c *gin.Context)

SteerInstall accepts administrator guidance for the displayed installation run.

func (*SandboxSkillHandler) Stop

func (h *SandboxSkillHandler) Stop(c *gin.Context)

Stop godoc @Summary Stop a skill install @Description Abort an in-flight install so the operator can retry or uninstall. After a process restart the row may still say installing with no live process; this rewrites it immediately instead of waiting for the stuck-run reaper. Removal is not stopped. @Tags SandboxConfig @Produce json @Param id path string true "Sandbox config ID" @Param skillId path string true "Skill ID" @Success 200 {object} map[string]interface{} "Stopped skill" @Failure 400 {object} apperrors.AppError "Skill is not installing" @Failure 401 {object} map[string]interface{} "Unauthorized" @Failure 404 {object} apperrors.AppError "Skill not found" @Security Bearer @Security ApiKeyAuth @Router /sandbox-configs/{id}/skills/{skillId}/stop [post]

func (*SandboxSkillHandler) Upload

func (h *SandboxSkillHandler) Upload(c *gin.Context)

Upload godoc @Summary Install a skill @Description Install a skill onto this sandbox config's image. Send a zip @Description as multipart form field "file", or JSON {"source":"..."} to @Description pull a public skill. source is one of: "@owner/slug" or a @Description slash-free slug (ClawHub), a github.com / gitlab.com / @Description skills.sh / clawhub / skillhub URL, a ClawHub skills-sh @Description catalog page (https://clawhub.ai/skills-sh/owner/repo/slug), @Description a skills-sh:owner/repo/slug locator, or a direct zip/SKILL.md @Description URL. Bare "owner/slug" is rejected as ambiguous. The source @Description must be readable anonymously. The install boots a sandbox and @Description runs for minutes, so the request is only accepted; follow it @Description via the install-events stream. @Tags SandboxConfig @Accept json @Accept multipart/form-data @Produce json @Param id path string true "Sandbox config ID" @Param file formData file false "Skill bundle (zip)" @Param request body skillSourceRequest false "Install from a registry, git host, or archive URL" @Success 202 {object} map[string]interface{} "Install accepted" @Failure 400 {object} apperrors.AppError "Missing, oversized or invalid bundle or source" @Failure 401 {object} map[string]interface{} "Unauthorized" @Failure 404 {object} apperrors.AppError "Sandbox config not found" @Security Bearer @Security ApiKeyAuth @Router /sandbox-configs/{id}/skills [post]

type SearchMessagesRequest

type SearchMessagesRequest struct {
	// Query text for search
	Query string `json:"query" binding:"required"`
	// Search mode: "keyword", "vector", "hybrid" (default: "hybrid")
	Mode string `json:"mode"`
	// Maximum number of results to return (default: 20)
	Limit int `json:"limit"`
	// Filter by specific session IDs (optional)
	SessionIDs []string `json:"session_ids"`
}

SearchMessagesRequest defines the request structure for searching messages

type SearchWikiRequest

type SearchWikiRequest struct {
	Query            string   `json:"query" binding:"required"`
	KnowledgeBaseID  string   `json:"knowledge_base_id"`
	KnowledgeBaseIDs []string `json:"knowledge_base_ids"`
	Limit            int      `json:"limit"`
}

SearchWikiRequest is the body for POST /api/v1/wiki-search.

type SetSharedAgentDisabledByMeRequest

type SetSharedAgentDisabledByMeRequest struct {
	AgentID  string `json:"agent_id" binding:"required"`
	Disabled bool   `json:"disabled"`
}

SetSharedAgentDisabledByMeRequest is the body for POST /shared-agents/disabled

type SetUserStatusRequest

type SetUserStatusRequest struct {
	UserID   string `json:"user_id" binding:"required"`
	IsActive *bool  `json:"is_active" binding:"required"`
}

SetUserStatusRequest toggles a user account enabled/disabled (SystemAdmin only).

type SkillHandler

type SkillHandler struct {
	// contains filtered or unexported fields
}

SkillHandler handles skill-related HTTP requests

func NewSkillHandler

func NewSkillHandler(
	usableSkills usableSkillLister,
	catalog skillCatalogService,
	agents access.SharedAgentLookup,
) *SkillHandler

NewSkillHandler creates a new skill handler. catalog may be nil in tests that only exercise the chat picker.

func (*SkillHandler) DeleteCatalog

func (h *SkillHandler) DeleteCatalog(c *gin.Context)

DeleteCatalog godoc @Summary Delete a catalog skill @Description Refused while any sandbox still has an installation of this skill. @Tags Skills @Param id path string true "Catalog skill ID" @Success 200 {object} map[string]interface{} @Router /skills/catalog/{id} [delete]

func (*SkillHandler) GetCatalogFile

func (h *SkillHandler) GetCatalogFile(c *gin.Context)

GetCatalogFile godoc @Summary Read one file of a catalog skill @Tags Skills @Produce json @Param id path string true "Catalog skill ID" @Param path query string true "Skill-root-relative file path" @Success 200 {object} map[string]interface{} @Router /skills/catalog/{id}/files/content [get]

func (*SkillHandler) InstallCatalog

func (h *SkillHandler) InstallCatalog(c *gin.Context)

InstallCatalog godoc @Summary Install a catalog skill onto sandboxes @Description Runs the existing snapshot install onto each named sandbox config. @Tags Skills @Accept json @Produce json @Param id path string true "Catalog skill ID" @Success 202 {object} map[string]interface{} @Router /skills/catalog/{id}/install [post]

func (*SkillHandler) ListCatalog

func (h *SkillHandler) ListCatalog(c *gin.Context)

ListCatalog godoc @Summary List workspace skills @Description Returns every skill definition in this workspace and which sandbox configs it is installed on. @Tags Skills @Produce json @Success 200 {object} map[string]interface{} @Security Bearer @Security ApiKeyAuth @Router /skills/catalog [get]

func (*SkillHandler) ListCatalogFiles

func (h *SkillHandler) ListCatalogFiles(c *gin.Context)

ListCatalogFiles godoc @Summary List files of a catalog skill @Description Lists the stored catalog bundle. Files belong to the skill definition, not a sandbox install. @Tags Skills @Produce json @Param id path string true "Catalog skill ID" @Success 200 {object} map[string]interface{} @Router /skills/catalog/{id}/files [get]

func (*SkillHandler) ListSkills

func (h *SkillHandler) ListSkills(c *gin.Context)

ListSkills godoc @Summary 获取当前沙箱配置上可执行的 Skills @Description 返回指定沙箱配置镜像内、智能体实际能调用的已安装技能(ready 且启用)。不传 sandbox_config_id 时列表为空。 @Tags Skills @Accept json @Produce json @Param sandbox_config_id query string false "Sandbox config ID; ignored for a shared agent" @Param agent_id query string false "Agent ID; needs agent_source_tenant_id" @Param agent_source_tenant_id query int false "Shared agent source workspace" @Success 200 {object} map[string]interface{} "Skills列表" @Failure 403 {object} errors.AppError "无权使用该共享智能体" @Security Bearer @Security ApiKeyAuth @Router /skills [get]

func (*SkillHandler) RegisterCatalog

func (h *SkillHandler) RegisterCatalog(c *gin.Context)

RegisterCatalog godoc @Summary Add a skill to the workspace catalog @Description Records a skill without installing it. Send a zip as multipart field "file", or JSON {"source":"..."}. @Tags Skills @Accept json @Accept multipart/form-data @Produce json @Success 201 {object} map[string]interface{} @Router /skills/catalog [post]

type SkillInfoResponse

type SkillInfoResponse struct {
	Name        string `json:"name"`
	Description string `json:"description"`
}

SkillInfoResponse represents the skill info returned to frontend

type StorageBackendHandler

type StorageBackendHandler struct {
	// contains filtered or unexported fields
}

func (*StorageBackendHandler) Create

func (h *StorageBackendHandler) Create(c *gin.Context)

Create godoc @Summary Create storage backend @Description Register a new object/file storage instance for the current workspace. The configuration is validated and a connectivity test is run before the backend is persisted. @Tags StorageBackend @Accept json @Produce json @Param request body storageBackendRequest true "Storage backend configuration" @Success 201 {object} map[string]interface{} "Created storage backend" @Failure 400 {object} apperrors.AppError "Invalid request, validation, or connectivity test failure" @Failure 401 {object} map[string]interface{} "Unauthorized" @Failure 409 {object} apperrors.AppError "A storage backend with this name already exists" @Security Bearer @Security ApiKeyAuth @Router /storage-backends [post]

func (*StorageBackendHandler) Delete

func (h *StorageBackendHandler) Delete(c *gin.Context)

Delete godoc @Summary Delete storage backend @Description Soft-delete a storage backend. A backend that is the workspace default, still bound to knowledge bases, environment-sourced, or a legacy alias cannot be deleted. @Tags StorageBackend @Produce json @Param id path string true "Storage backend ID" @Success 200 {object} map[string]interface{} "Deletion success" @Failure 400 {object} apperrors.AppError "Backend is default, bound, read-only, or legacy alias" @Failure 401 {object} map[string]interface{} "Unauthorized" @Failure 404 {object} apperrors.AppError "Storage backend not found" @Security Bearer @Security ApiKeyAuth @Router /storage-backends/{id} [delete]

func (*StorageBackendHandler) Get

func (h *StorageBackendHandler) Get(c *gin.Context)

Get godoc @Summary Get storage backend @Description Retrieve a single storage backend by ID for the current workspace. Credentials are masked. @Tags StorageBackend @Produce json @Param id path string true "Storage backend ID" @Success 200 {object} map[string]interface{} "Storage backend details" @Failure 401 {object} map[string]interface{} "Unauthorized" @Failure 404 {object} apperrors.AppError "Storage backend not found" @Security Bearer @Security ApiKeyAuth @Router /storage-backends/{id} [get]

func (*StorageBackendHandler) List

func (h *StorageBackendHandler) List(c *gin.Context)

List godoc @Summary List storage backends @Description List all storage backend instances for the current workspace, with credentials masked. The workspace default backend id is returned alongside the list. @Tags StorageBackend @Produce json @Success 200 {object} map[string]interface{} "List of storage backends and default_storage_backend_id" @Failure 401 {object} map[string]interface{} "Unauthorized" @Security Bearer @Security ApiKeyAuth @Router /storage-backends [get]

func (*StorageBackendHandler) SetDefault

func (h *StorageBackendHandler) SetDefault(c *gin.Context)

SetDefault godoc @Summary Set default storage backend @Description Mark a storage backend as the workspace default. Only an active backend can become the default. New knowledge bases without an explicit binding use the default. @Tags StorageBackend @Produce json @Param id path string true "Storage backend ID" @Success 200 {object} map[string]interface{} "Default set successfully" @Failure 400 {object} apperrors.AppError "Backend is not active" @Failure 401 {object} map[string]interface{} "Unauthorized" @Failure 404 {object} apperrors.AppError "Storage backend not found" @Security Bearer @Security ApiKeyAuth @Router /storage-backends/{id}/default [put]

func (*StorageBackendHandler) TestByID

func (h *StorageBackendHandler) TestByID(c *gin.Context)

TestByID godoc @Summary Test storage backend by ID @Description Test connectivity of an existing saved storage backend using its stored credentials. Returns success=false with a sanitized error message on failure (the HTTP status stays 200). @Tags StorageBackend @Produce json @Param id path string true "Storage backend ID" @Success 200 {object} map[string]interface{} "Connectivity test result (success, error)" @Failure 401 {object} map[string]interface{} "Unauthorized" @Failure 404 {object} apperrors.AppError "Storage backend not found" @Security Bearer @Security ApiKeyAuth @Router /storage-backends/{id}/test [post]

func (*StorageBackendHandler) TestRaw

func (h *StorageBackendHandler) TestRaw(c *gin.Context)

TestRaw godoc @Summary Test storage backend with raw config @Description Test connectivity for the provided storage configuration without persisting it. Returns success=false with a sanitized error message on failure (the HTTP status stays 200). @Tags StorageBackend @Accept json @Produce json @Param request body storageBackendRequest true "Storage backend configuration to test" @Success 200 {object} map[string]interface{} "Connectivity test result (success, error)" @Failure 400 {object} apperrors.AppError "Invalid request or validation error" @Failure 401 {object} map[string]interface{} "Unauthorized" @Security Bearer @Security ApiKeyAuth @Router /storage-backends/test [post]

func (*StorageBackendHandler) Types

func (h *StorageBackendHandler) Types(c *gin.Context)

Types godoc @Summary List allowed storage provider types @Description Return the storage provider types allowed by STORAGE_ALLOW_LIST for UI form generation (e.g. local, minio, cos, tos, s3, oss, ks3, obs). @Tags StorageBackend @Produce json @Success 200 {object} map[string]interface{} "List of allowed storage provider types" @Security Bearer @Security ApiKeyAuth @Router /storage-backends/types [get]

func (*StorageBackendHandler) Update

func (h *StorageBackendHandler) Update(c *gin.Context)

Update godoc @Summary Update storage backend @Description Update a storage backend's mutable fields (name, credentials, status). Provider and physical location (endpoint, region, bucket, path prefix) are immutable; use storage migration to move data. Environment-sourced backends are read-only. Redacted secret placeholders preserve the stored credentials. @Tags StorageBackend @Accept json @Produce json @Param id path string true "Storage backend ID" @Param request body storageBackendRequest true "Updated storage backend fields" @Success 200 {object} map[string]interface{} "Updated storage backend" @Failure 400 {object} apperrors.AppError "Immutable field change, read-only backend, validation, or connectivity failure" @Failure 401 {object} map[string]interface{} "Unauthorized" @Failure 404 {object} apperrors.AppError "Storage backend not found" @Security Bearer @Security ApiKeyAuth @Router /storage-backends/{id} [put]

type StorageCheckRequest

type StorageCheckRequest struct {
	Provider string                   `json:"provider"` // "minio", "cos", "tos", "s3", "oss", "ks3", "obs"
	MinIO    *types.MinIOEngineConfig `json:"minio,omitempty"`
	COS      *types.COSEngineConfig   `json:"cos,omitempty"`
	TOS      *types.TOSEngineConfig   `json:"tos,omitempty"`
	S3       *types.S3EngineConfig    `json:"s3,omitempty"`
	OSS      *types.OSSEngineConfig   `json:"oss,omitempty"`
	KS3      *types.KS3EngineConfig   `json:"ks3,omitempty"`
	OBS      *types.OBSEngineConfig   `json:"obs,omitempty"`
}

StorageCheckRequest is the body for POST /system/storage-engine-check.

type StorageCheckResponse

type StorageCheckResponse struct {
	OK            bool   `json:"ok"`
	Message       string `json:"message"`
	BucketCreated bool   `json:"bucket_created,omitempty"`
}

StorageCheckResponse is the response for a single-engine connectivity check.

type StorageEngineStatusItem

type StorageEngineStatusItem struct {
	Name        string `json:"name"` // "local", "minio", "cos", "tos", "s3", "oss", "ks3", "obs"
	Allowed     bool   `json:"allowed"`
	Available   bool   `json:"available"`   // whether the engine can be used
	Description string `json:"description"` // short description for UI
}

StorageEngineStatusItem describes one storage engine's availability and description.

type SuggestionEventRequest

type SuggestionEventRequest struct {
	SuggestionSetID string `json:"suggestion_set_id" binding:"required"`
	QuestionID      string `json:"question_id"`
	EventType       string `json:"event_type" binding:"required"`
}

type SystemHandler

type SystemHandler struct {
	// contains filtered or unexported fields
}

SystemHandler handles system-related requests

func NewSystemHandler

func NewSystemHandler(cfg *config.Config,
	neo4jDriver neo4j.Driver,
	documentReader interfaces.DocumentReader,
	tenantSvc interfaces.TenantService,
	userSvc interfaces.UserService,
	systemSettingSvc interfaces.SystemSettingService,
	modelCatalogSvc *service.ModelCatalogService,
	apiKeySvc interfaces.TenantAPIKeyService,
	auditSvc interfaces.AuditLogService,
	taskInspector interfaces.TaskInspector,
	knowledgeSvc interfaces.KnowledgeService,
	storageBackendRepo interfaces.StorageBackendRepository,
	sandboxConfigSvc *service.TenantSandboxConfigService,
) *SystemHandler

NewSystemHandler creates a new system handler

func (*SystemHandler) ApplyDefaultStorageQuotaToAllTenants

func (h *SystemHandler) ApplyDefaultStorageQuotaToAllTenants(c *gin.Context)

ApplyDefaultStorageQuotaToAllTenants godoc @Summary Apply the default storage quota to every existing workspace @Description Reads the current value of `tenant.default_storage_quota_gb` @Description (3-tier resolver: DB > ENV > default) and writes that many @Description GiB into storage_quota for every row in tenants. Bypasses @Description the per-workspace PUT whitelist, which forbids storage_quota @Description edits by Owners. SystemAdmin only. @Description Idempotent — running twice with the same setting is a no-op. @Tags System Admin @Produce json @Success 200 {object} map[string]interface{} "{ affected: int64, quota_bytes: int64 }" @Failure 500 {object} map[string]interface{} "DB write failed" @Router /system/admin/tenants/apply-default-storage-quota [post]

func (*SystemHandler) BindDeploymentCapabilities

func (h *SystemHandler) BindDeploymentCapabilities(data DeploymentCapabilitiesData)

BindDeploymentCapabilities stores the startup snapshot used by GetDeploymentCapabilities.

func (*SystemHandler) CheckParserEngines

func (h *SystemHandler) CheckParserEngines(c *gin.Context)

CheckParserEngines runs availability check with the given config overrides (e.g. current form values). Used to test engine availability without saving; body shape matches ParserEngineConfig. @Summary 使用当前参数检测解析引擎可用性 @Tags 系统 @Accept json @Produce json @Param body body object true "解析引擎配置(与保存接口同结构)" @Success 200 @Router /system/parser-engines/check [post]

func (*SystemHandler) CheckSandboxConfig

func (h *SystemHandler) CheckSandboxConfig(c *gin.Context)

CheckSandboxConfig tests a sandbox configuration without persisting it. @Summary 测试沙箱连通性 @Description 使用当前填写的参数测试沙箱后端,不保存配置;deep=true 会执行临时脚本,远端后端还会创建并销毁一个沙箱 @Tags 系统 @Accept json @Produce json @Param body body SandboxCheckRequest true "沙箱配置" @Success 200 {object} SandboxCheckResponse @Router /system/sandbox-check [post]

func (*SystemHandler) CheckStorageEngine

func (h *SystemHandler) CheckStorageEngine(c *gin.Context)

CheckStorageEngine tests connectivity for a single storage engine using the provided config. @Summary 测试存储引擎连通性 @Description 使用当前填写的参数测试 MinIO/COS 连通性,不保存配置 @Tags 系统 @Accept json @Produce json @Param body body StorageCheckRequest true "存储引擎配置" @Success 200 {object} StorageCheckResponse @Router /system/storage-engine-check [post]

func (*SystemHandler) CreatePlatformAPIKey

func (h *SystemHandler) CreatePlatformAPIKey(c *gin.Context)

CreatePlatformAPIKey godoc @Summary Create a platform API key @Description Creates a capability-scoped key that may target any workspace through X-Tenant-ID. The plaintext token is returned once. Human SystemAdmin only. @Tags System Admin @Accept json @Produce json @Param request body platformAPIKeyCreateRequest true "Platform API key" @Success 201 {object} map[string]interface{} @Security Bearer @Router /system/admin/api-keys [post]

func (*SystemHandler) CreateSystemUser

func (h *SystemHandler) CreateSystemUser(c *gin.Context)

CreateSystemUser godoc @Summary Create a new user (SystemAdmin) @Description Provision a new local user account (SystemAdmin only). @Description When `password` is omitted or null, a cryptographically random @Description password is generated (OIDC-style crypto/rand + base64url) @Description and returned once in the response body. Any provided value, @Description including empty string, is policy-checked. Tenant provisioning @Description follows the shared auth.default_tenant_mode policy. @Tags System Admin @Accept json @Produce json @Param request body types.AdminCreateUserRequest true "User creation request" @Success 201 {object} CreateSystemUserResponse "User created successfully" @Success 200 {object} CreateSystemUserResponse "Identity already exists, returns the existing user" @Failure 400 {object} map[string]interface{} "Invalid request or weak password" @Failure 403 {object} map[string]interface{} "Forbidden: not a system admin" @Failure 409 {object} map[string]interface{} "Email and username refer to conflicting identities" @Failure 500 {object} map[string]interface{} "Internal error" @Router /system/admin/users/create [post]

func (*SystemHandler) DeletePlatformAPIKey

func (h *SystemHandler) DeletePlatformAPIKey(c *gin.Context)

DeletePlatformAPIKey godoc @Summary Revoke a platform API key @Description Immediately revokes a platform API key. Human SystemAdmin only. @Tags System Admin @Produce json @Param key_id path int true "API key ID" @Success 200 {object} map[string]interface{} @Security Bearer @Router /system/admin/api-keys/{key_id} [delete]

func (*SystemHandler) GetDeploymentCapabilities

func (h *SystemHandler) GetDeploymentCapabilities(c *gin.Context)

GetDeploymentCapabilities godoc @Summary 获取部署能力清单 @Description 返回当前部署版本及实际注册的后端路由所对应的功能能力;仅 supported=false 表示入口应隐藏 @Tags 系统 @Produce json @Success 200 {object} map[string]interface{} "标准 code/msg/data 包装,data 为 DeploymentCapabilitiesData" @Router /system/capabilities [get]

func (*SystemHandler) GetModelCatalog

func (h *SystemHandler) GetModelCatalog(c *gin.Context)

GetModelCatalog returns the catalog layers, overlay and version history. @Summary Get the system model catalog @Description System administrator JWT only; API keys are not accepted. Returns built-in, deployment and effective @Description catalogs, the current overlay, version/baseline tokens, and the latest 20 published revisions. @Tags 系统管理 @Produce json @Success 200 {object} service.CatalogState @Failure 401 {object} map[string]interface{} @Failure 403 {object} map[string]interface{} @Failure 503 {object} map[string]interface{} @Security Bearer @Router /system/admin/model-catalog [get]

func (*SystemHandler) GetRuntimeQueues

func (h *SystemHandler) GetRuntimeQueues(c *gin.Context)

GetRuntimeQueues godoc @Summary 获取解析任务队列运行时状态 @Description 返回各 asynq 队列的实时深度(pending/active/scheduled/retry 等)与 worker 并发配置,仅系统管理员可见 @Tags 系统管理 @Produce json @Success 200 {object} RuntimeQueuesResponse @Router /system/admin/runtime/queues [get]

func (*SystemHandler) GetStorageEngineStatus

func (h *SystemHandler) GetStorageEngineStatus(c *gin.Context)

GetStorageEngineStatus godoc @Summary 获取存储引擎状态 @Description 返回 Local、MinIO、COS 各存储引擎的可用状态及说明,供全局设置与知识库选择使用 @Tags 系统 @Produce json @Success 200 {object} GetStorageEngineStatusResponse @Router /system/storage-engine-status [get]

func (*SystemHandler) GetSystemInfo

func (h *SystemHandler) GetSystemInfo(c *gin.Context)

GetSystemInfo godoc @Summary 获取系统信息 @Description 获取系统版本、构建信息和引擎配置 @Tags 系统 @Accept json @Produce json @Success 200 {object} GetSystemInfoResponse "系统信息" @Router /system/info [get]

func (*SystemHandler) GetSystemSetting

func (h *SystemHandler) GetSystemSetting(c *gin.Context)

GetSystemSetting godoc @Summary Get a single system setting by key @Description Returns the row matching :key. 404 when the key is unknown @Description to the registry; 200 with the row when known. @Tags System Admin @Produce json @Param key path string true "Setting key (e.g. file.max_size_mb)" @Success 200 {object} types.SystemSetting "the setting row" @Failure 400 {object} map[string]interface{} "Unknown key" @Failure 404 {object} map[string]interface{} "Key registered but DB row absent" @Router /system/admin/settings/{key} [get]

func (*SystemHandler) ListParserEngines

func (h *SystemHandler) ListParserEngines(c *gin.Context)

ListParserEngines returns available document parser engines. Merges Go-native static engines with engines discovered from the remote docreader service, so newly added Python engines are auto-discovered. @Summary 列出可用的文档解析引擎 @Tags 系统 @Produce json @Success 200 {object} map[string]interface{} "解析引擎列表" @Router /system/parser-engines [get]

func (*SystemHandler) ListPlatformAPIKeys

func (h *SystemHandler) ListPlatformAPIKeys(c *gin.Context)

ListPlatformAPIKeys godoc @Summary List platform API keys @Description Lists non-workspace API keys. Full tokens are always masked. Human SystemAdmin only. @Tags System Admin @Produce json @Success 200 {object} map[string]interface{} @Security Bearer @Router /system/admin/api-keys [get]

func (*SystemHandler) ListRuntimeTasks

func (h *SystemHandler) ListRuntimeTasks(c *gin.Context)

ListRuntimeTasks returns one live task-state page for the unified operator drawer. Raw task payloads are never included. @Summary List runtime queue tasks by state @Tags System Admin @Produce json @Param queue path string true "Queue name" @Param state query string true "Task state" Enums(pending,active,scheduled,retry,archived,completed) @Param cursor query string false "Opaque continuation cursor" @Param page_size query int false "Page size" default(20) @Success 200 {object} RuntimeTasksResponse @Router /system/admin/runtime/queues/{queue}/tasks [get]

func (*SystemHandler) ListSystemAdmins

func (h *SystemHandler) ListSystemAdmins(c *gin.Context)

ListSystemAdmins godoc @Summary List all system administrators @Description Retrieve a paginated list of users with system administrator @Description privileges (SystemAdmin only). Supports `offset` (default 0) @Description and `limit` (default 50, max 200) query parameters. Walks the @Description partial-friendly idx_users_is_system_admin index. @Tags System Admin @Produce json @Param offset query int false "Page offset" default(0) @Param limit query int false "Page size (max 200)" default(50) @Success 200 {object} ListSystemAdminsResponse "System admins retrieved successfully" @Failure 403 {object} map[string]interface{} "Forbidden: not a system admin" @Router /system/admin/list [get]

func (*SystemHandler) ListSystemSettings

func (h *SystemHandler) ListSystemSettings(c *gin.Context)

func (*SystemHandler) ListUsers

func (h *SystemHandler) ListUsers(c *gin.Context)

ListUsers godoc @Summary List all platform users @Description Retrieve a paginated list of every user across tenants (SystemAdmin only). @Description Supports `offset` (default 0) and `limit` (default 50, max 200). @Description Password/hashes are never serialised — only the redacted UserInfo shape. @Tags System Admin @Produce json @Param offset query int false "Page offset" default(0) @Param limit query int false "Page size (max 200)" default(50) @Success 200 {object} ListAllUsersResponse "Users retrieved successfully" @Failure 403 {object} map[string]interface{} "Forbidden: not a system admin" @Router /system/admin/users [get]

func (*SystemHandler) MutateRuntimeTask

func (h *SystemHandler) MutateRuntimeTask(c *gin.Context)

MutateRuntimeTask executes a backend-advertised action after re-reading the current task state to close click/race windows. @Summary Run a safe runtime task action @Tags System Admin @Produce json @Param queue path string true "Queue name" @Param task_id path string true "Task ID" @Param action path string true "Action" Enums(cancel,run_now,delete) @Success 200 {object} map[string]bool @Router /system/admin/runtime/queues/{queue}/tasks/{task_id}/actions/{action} [post]

func (*SystemHandler) PickHostProjectDir

func (*SystemHandler) PickHostProjectDir(c *gin.Context)

PickHostProjectDir opens the system folder picker. The SPA talks HTTP to this process; Wails JS bindings are not injected through the reverse-proxied frontend, so this is the working authorization path.

func (*SystemHandler) PreviewModelCatalog

func (h *SystemHandler) PreviewModelCatalog(c *gin.Context)

PreviewModelCatalog validates an overlay and returns the candidate catalog. @Summary Preview a model catalog overlay @Description System administrator JWT only; API keys are not accepted. Validates the overlay without publishing @Description it. Supply the current version and baseline; stale values return 409. The response contains the @Description candidate effective catalog and normalized overlay; history, builtin and deployment are null. @Tags 系统管理 @Accept json @Produce json @Param request body service.CatalogUpdate true "Version, baseline and overlay object (max 1 MiB)" @Success 200 {object} service.CatalogState @Failure 400 {object} map[string]interface{} @Failure 401 {object} map[string]interface{} @Failure 403 {object} map[string]interface{} @Failure 409 {object} map[string]interface{} @Failure 500 {object} map[string]interface{} @Security Bearer @Router /system/admin/model-catalog/preview [post]

func (*SystemHandler) PromoteUserToSystemAdmin

func (h *SystemHandler) PromoteUserToSystemAdmin(c *gin.Context)

PromoteUserToSystemAdmin godoc @Summary Promote a user to system administrator @Description Grant system administrator privileges to a user (SystemAdmin only). @Description Idempotent: re-promoting an existing system admin returns 200 with no DB write. @Description Identify the user by email (preferred for human operators) or user_id (UUID, for API clients). @Tags System Admin @Accept json @Produce json @Param request body PromoteUserToSystemAdminRequest true "User promotion request" @Success 200 {object} types.UserInfo "User promoted successfully" @Failure 400 {object} map[string]interface{} "Bad request" @Failure 403 {object} map[string]interface{} "Forbidden: not a system admin" @Failure 404 {object} map[string]interface{} "User not found" @Router /system/admin/promote [post]

func (*SystemHandler) PublishModelCatalog

func (h *SystemHandler) PublishModelCatalog(c *gin.Context)

PublishModelCatalog validates, persists and applies an overlay. @Summary Publish a model catalog overlay @Description System administrator JWT only; API keys are not accepted. Validates and publishes a new overlay @Description revision using the current version and baseline. Stale values return 409. To restore a historical @Description configuration, submit its overlay with the current version and baseline. @Tags 系统管理 @Accept json @Produce json @Param request body service.CatalogUpdate true "Version, baseline and overlay object (max 1 MiB)" @Success 200 {object} service.CatalogState @Failure 400 {object} map[string]interface{} @Failure 401 {object} map[string]interface{} @Failure 403 {object} map[string]interface{} @Failure 409 {object} map[string]interface{} @Failure 500 {object} map[string]interface{} @Security Bearer @Router /system/admin/model-catalog [put]

func (*SystemHandler) PurgeArchivedRuntimeTasks

func (h *SystemHandler) PurgeArchivedRuntimeTasks(c *gin.Context)

PurgeArchivedRuntimeTasks clears every archived (finally-failed) task in one queue. It only touches the archived dead-letter set — live pending/active/ scheduled/retry tasks are untouched — and mirrors single-record delete semantics by leaving business state as-is (archived tasks already had their document status flipped to "failed" on their last retry). @Summary Purge all archived tasks in a queue @Tags System Admin @Produce json @Param queue path string true "Queue name" @Success 200 {object} map[string]interface{} @Router /system/admin/runtime/queues/{queue}/archived [delete]

func (*SystemHandler) ReconnectDocReader

func (h *SystemHandler) ReconnectDocReader(c *gin.Context)

ReconnectDocReader reconnects the document converter to a new (or same) DocReader address. @Summary 重连文档解析服务 @Tags 系统 @Accept json @Produce json @Param request body object{addr string} true "DocReader 地址" @Success 200 @Router /system/docreader/reconnect [post]

func (*SystemHandler) ResetSystemSetting

func (h *SystemHandler) ResetSystemSetting(c *gin.Context)

ResetSystemSetting godoc @Summary Reset a system setting to ENV / built-in default @Description Removes the DB override for :key so the 3-tier resolver @Description falls back to the environment variable (when configured) @Description or the in-code default. Idempotent — resetting a key @Description that was never persisted returns 200. @Tags System Admin @Param key path string true "Setting key" @Success 200 {object} map[string]interface{} "Reset acknowledged" @Failure 400 {object} map[string]interface{} "Unknown key" @Failure 500 {object} map[string]interface{} "DB write failed" @Router /system/admin/settings/{key} [delete]

func (*SystemHandler) ResetUserPassword

func (h *SystemHandler) ResetUserPassword(c *gin.Context)

ResetUserPassword godoc @Summary Reset another user's password @Description Replace another user's local password and revoke all of their existing sessions (SystemAdmin only). @Description A system administrator cannot reset their own password through this endpoint; self-service password change still requires the old password. @Tags System Admin @Accept json @Produce json @Param request body ResetUserPasswordRequest true "Password reset request" @Success 200 {object} map[string]interface{} "Password reset successfully" @Failure 400 {object} map[string]interface{} "Invalid request, weak password, or self reset" @Failure 403 {object} map[string]interface{} "Forbidden: not a system admin" @Failure 404 {object} map[string]interface{} "User not found" @Router /system/admin/users/reset-password [post]

func (*SystemHandler) ResolveDocumentReader

func (h *SystemHandler) ResolveDocumentReader(ctx context.Context, addr string) interfaces.DocumentReader

func (*SystemHandler) RevokeSystemAdmin

func (h *SystemHandler) RevokeSystemAdmin(c *gin.Context)

RevokeSystemAdmin godoc @Summary Revoke system administrator privileges from a user @Description Remove system administrator privileges from a user (SystemAdmin only). @Description Two safety guards: the caller cannot revoke their own privileges, @Description and revoking the last remaining system admin is rejected — both @Description prevent a SystemAdmin from accidentally locking the platform out @Description of system-level administration. Idempotent on already-non-admin users. @Tags System Admin @Accept json @Produce json @Param request body RevokeSystemAdminRequest true "User revocation request" @Success 200 {object} types.UserInfo "Privileges revoked successfully" @Failure 400 {object} map[string]interface{} "Bad request / would remove last admin / self-revoke" @Failure 403 {object} map[string]interface{} "Forbidden: not a system admin" @Failure 404 {object} map[string]interface{} "User not found" @Router /system/admin/revoke [post]

func (*SystemHandler) SetUserStatus

func (h *SystemHandler) SetUserStatus(c *gin.Context)

SetUserStatus godoc @Summary Enable or disable a user account @Description Disable revokes the target's active sessions immediately. @Description Self-disable and disabling the last active system administrator are rejected. @Tags System Admin @Accept json @Produce json @Param request body SetUserStatusRequest true "Account status request" @Success 200 {object} map[string]interface{} "Status updated" @Failure 400 {object} map[string]interface{} "Self-disable / last-admin guard" @Failure 404 {object} map[string]interface{} "User not found" @Router /system/admin/users/status [post]

func (*SystemHandler) UpdateSystemSetting

func (h *SystemHandler) UpdateSystemSetting(c *gin.Context)

UpdateSystemSetting godoc @Summary Update a system setting value @Description Persist a new value for :key. Service validates the @Description rawValue against the registry's declared value_type and @Description rejects mismatches with 400. SystemAdmin only. Emits an @Description audit row (action=system.setting_changed) on success. @Tags System Admin @Accept json @Produce json @Param key path string true "Setting key" @Param request body UpdateSystemSettingRequest true "New value" @Success 200 {object} types.SystemSetting "the updated row" @Failure 400 {object} map[string]interface{} "Bad request / unknown key / type mismatch" @Failure 403 {object} map[string]interface{} "Forbidden: not a system admin" @Router /system/admin/settings/{key} [put]

type TagHandler

type TagHandler struct {
	// contains filtered or unexported fields
}

TagHandler handles knowledge base tag operations.

All KB-access checks (own / org-shared / via shared agent) are now performed by the route-level g.KBAccessRead / g.KBAccessWrite guards in router.go — the guard rewrites c.Request.Context() to carry the effective tenant ID, so handlers below just use c.Request.Context() the way they always did.

func NewTagHandler

NewTagHandler creates a new TagHandler.

func (*TagHandler) CreateTag

func (h *TagHandler) CreateTag(c *gin.Context)

CreateTag godoc @Summary 创建标签 @Description 在知识库下创建新标签 @Tags 标签管理 @Accept json @Produce json @Param id path string true "知识库ID" @Param request body object{name=string,color=string,sort_order=int} true "标签信息" @Success 200 {object} map[string]interface{} "创建的标签" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /knowledge-bases/{id}/tags [post]

func (*TagHandler) DeleteTag

func (h *TagHandler) DeleteTag(c *gin.Context)

DeleteTag godoc @Summary 删除标签 @Description 删除标签,可使用force=true强制删除被引用的标签,content_only=true仅删除标签下的内容而保留标签本身 @Tags 标签管理 @Accept json @Produce json @Param id path string true "知识库ID" @Param tag_id path string true "标签ID (UUID或seq_id)" @Param force query bool false "强制删除" @Param content_only query bool false "仅删除内容,保留标签" @Param body body DeleteTagRequest false "删除选项" @Success 200 {object} map[string]interface{} "删除成功" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /knowledge-bases/{id}/tags/{tag_id} [delete]

func (*TagHandler) ListTags

func (h *TagHandler) ListTags(c *gin.Context)

ListTags godoc @Summary 获取标签列表 @Description 获取知识库下的所有标签及统计信息 @Tags 标签管理 @Accept json @Produce json @Param id path string true "知识库ID" @Param page query int false "页码" @Param page_size query int false "每页数量" @Param keyword query string false "关键词搜索" @Success 200 {object} map[string]interface{} "标签列表" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /knowledge-bases/{id}/tags [get]

func (*TagHandler) UpdateTag

func (h *TagHandler) UpdateTag(c *gin.Context)

UpdateTag godoc @Summary 更新标签 @Description 更新标签信息 @Tags 标签管理 @Accept json @Produce json @Param id path string true "知识库ID" @Param tag_id path string true "标签ID (UUID或seq_id)" @Param request body object true "标签更新信息" @Success 200 {object} map[string]interface{} "更新后的标签" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /knowledge-bases/{id}/tags/{tag_id} [put]

type TenantHandler

type TenantHandler struct {
	// contains filtered or unexported fields
}

TenantHandler implements HTTP request handlers for tenant management Provides functionality for creating, retrieving, updating, and deleting tenants through the REST API endpoints

func NewTenantHandler

func NewTenantHandler(
	service interfaces.TenantService,
	apiKeyService interfaces.TenantAPIKeyService,
	userService interfaces.UserService,
	memberService interfaces.TenantMemberService,
	kbService interfaces.KnowledgeBaseService,
	config *config.Config,
	systemSettingSvc interfaces.SystemSettingService,
) *TenantHandler

NewTenantHandler creates a new tenant handler instance with the provided service Parameters:

  • service: An implementation of the TenantService interface for business logic
  • userService: An implementation of the UserService interface for user operations
  • memberService: An implementation of TenantMemberService used to bootstrap the creator as Owner of the tenant they just created (self-service create).
  • config: Application configuration

Returns a pointer to the newly created TenantHandler

Note on RBAC: cross-tenant gating (CanAccessAllTenants / EnableCrossTenantAccess) and per-tenant path matching (URL :id == active tenant) used to live in `authorizeTenantAccess` and the if blocks at the top of ListAllTenants / SearchTenants. Both moved to `middleware/access.go` (RequireCrossTenantAccess / RequirePathTenantMatch) and are wired in `router.go` so the handler stays focused on business logic.

func (*TenantHandler) CreateAPIKey

func (h *TenantHandler) CreateAPIKey(c *gin.Context)

func (*TenantHandler) CreateAPIPrincipalTestToken

func (h *TenantHandler) CreateAPIPrincipalTestToken(c *gin.Context)

CreateAPIPrincipalTestToken godoc @Summary 生成 API Playground 测试 JWT @Description 使用空间已保存的 HMAC 密钥签发短期外部用户 JWT(Owner) @Tags 空间管理 @Accept json @Produce json @Param id path int true "空间ID" @Param request body handler.apiPrincipalTestTokenRequest true "测试 Token 参数" @Success 200 {object} map[string]interface{} "短期 JWT" @Failure 400 {object} errors.AppError "请求参数错误" @Failure 403 {object} errors.AppError "权限不足" @Security Bearer @Router /tenants/{id}/api-principal-test-token [post]

func (*TenantHandler) CreateTenant

func (h *TenantHandler) CreateTenant(c *gin.Context)

CreateTenant godoc @Summary 创建空间 @Description 创建新的空间。任意已登录用户均可调用以建立自己的新工作区, @Description 调用方会被自动设为该空间的 Owner。跨空间超管仍可像以前一样 @Description 通过本接口创建任意空间。 @Description 当 tenant.auto_create_api_key(或 WEKNORA_TENANT_AUTO_CREATE_API_KEY) @Description 开启时,会自动创建一个 full_access API Key,并在响应体的 data.api_key 字段返回其明文 token。 @Tags 空间管理 @Accept json @Produce json @Param request body handler.createTenantRequest true "空间信息" @Success 201 {object} map[string]interface{} "创建的空间(可选含 api_key)" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Router /tenants [post]

func (*TenantHandler) DeleteAPIKey

func (h *TenantHandler) DeleteAPIKey(c *gin.Context)

func (*TenantHandler) DeleteTenant

func (h *TenantHandler) DeleteTenant(c *gin.Context)

DeleteTenant godoc @Summary 删除空间 @Description 删除指定的空间 @Tags 空间管理 @Accept json @Produce json @Param id path int true "空间ID" @Success 200 {object} map[string]interface{} "删除成功" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Router /tenants/{id} [delete]

func (*TenantHandler) GetAPIPrincipalConfig

func (h *TenantHandler) GetAPIPrincipalConfig(c *gin.Context)

GetAPIPrincipalConfig godoc @Summary 获取空间 API Key 用户身份配置 @Description 返回 X-API-Key 请求如何映射为终端 Principal 的配置(Owner) @Tags 空间管理 @Accept json @Produce json @Param id path int true "空间ID" @Success 200 {object} map[string]interface{} "API principal 配置" @Failure 400 {object} errors.AppError "请求参数错误" @Failure 403 {object} errors.AppError "权限不足" @Security Bearer @Router /tenants/{id}/api-principal-config [get]

func (*TenantHandler) GetPromptTemplates

func (h *TenantHandler) GetPromptTemplates(c *gin.Context)

GetPromptTemplates godoc @Summary 获取提示词模板 @Description 获取系统配置的提示词模板列表 @Tags 空间管理 @Accept json @Produce json @Success 200 {object} map[string]interface{} "提示词模板配置" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /tenants/kv/prompt-templates [get]

func (*TenantHandler) GetTenant

func (h *TenantHandler) GetTenant(c *gin.Context)

GetTenant godoc @Summary 获取空间详情 @Description 根据ID获取空间详情 @Tags 空间管理 @Accept json @Produce json @Param id path int true "空间ID" @Success 200 {object} map[string]interface{} "空间详情" @Failure 400 {object} errors.AppError "请求参数错误" @Failure 404 {object} errors.AppError "空间不存在" @Security Bearer @Security ApiKeyAuth @Router /tenants/{id} [get]

func (*TenantHandler) GetTenantChatHistoryConfig

func (h *TenantHandler) GetTenantChatHistoryConfig(c *gin.Context)

GetTenantChatHistoryConfig returns the tenant's chat history KB configuration.

func (*TenantHandler) GetTenantKV

func (h *TenantHandler) GetTenantKV(c *gin.Context)

GetTenantKV godoc @Summary 获取空间KV配置 @Description 获取空间级别的KV配置(支持web-search-config、prompt-templates、parser-engine-config、storage-engine-config、chat-history-config、retrieval-config) @Tags 空间管理 @Accept json @Produce json @Param key path string true "配置键名" @Success 200 {object} map[string]interface{} "配置值" @Failure 400 {object} errors.AppError "不支持的键" @Security Bearer @Security ApiKeyAuth @Router /tenants/kv/{key} [get]

func (*TenantHandler) GetTenantMemoryConfig

func (h *TenantHandler) GetTenantMemoryConfig(c *gin.Context)

GetTenantMemoryConfig returns the workspace long-term memory configuration.

func (*TenantHandler) GetTenantParserEngineConfig

func (h *TenantHandler) GetTenantParserEngineConfig(c *gin.Context)

GetTenantParserEngineConfig returns the tenant's parser engine config (MinerU endpoint, API key, etc.).

func (*TenantHandler) GetTenantRetrievalConfig

func (h *TenantHandler) GetTenantRetrievalConfig(c *gin.Context)

GetTenantRetrievalConfig returns the tenant's global retrieval configuration.

func (*TenantHandler) GetTenantStorageEngineConfig

func (h *TenantHandler) GetTenantStorageEngineConfig(c *gin.Context)

GetTenantStorageEngineConfig returns the tenant's storage engine config (Local, MinIO, COS parameters).

func (*TenantHandler) GetTenantWebSearchConfig

func (h *TenantHandler) GetTenantWebSearchConfig(c *gin.Context)

GetTenantWebSearchConfig godoc @Summary 获取空间网络搜索配置 @Description 获取空间的网络搜索配置 @Tags 空间管理 @Accept json @Produce json @Success 200 {object} map[string]interface{} "网络搜索配置" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /tenants/kv/web-search-config [get]

func (*TenantHandler) ListAPIKeys

func (h *TenantHandler) ListAPIKeys(c *gin.Context)

func (*TenantHandler) ListAllTenants

func (h *TenantHandler) ListAllTenants(c *gin.Context)

ListAllTenants godoc @Summary 获取所有空间列表 @Description 获取系统中所有空间(需要跨空间访问权限) @Tags 空间管理 @Accept json @Produce json @Success 200 {object} map[string]interface{} "所有空间列表" @Failure 403 {object} errors.AppError "权限不足" @Security Bearer @Router /tenants/all [get]

func (*TenantHandler) ListTenants

func (h *TenantHandler) ListTenants(c *gin.Context)

ListTenants godoc @Summary 获取空间列表 @Description 获取当前用户可访问的空间列表 @Tags 空间管理 @Accept json @Produce json @Success 200 {object} map[string]interface{} "空间列表" @Failure 500 {object} errors.AppError "服务器错误" @Security Bearer @Router /tenants [get]

func (*TenantHandler) SearchTenants

func (h *TenantHandler) SearchTenants(c *gin.Context)

SearchTenants godoc @Summary 搜索空间 @Description 分页搜索空间(需要跨空间访问权限) @Tags 空间管理 @Accept json @Produce json @Param keyword query string false "搜索关键词" @Param tenant_id query int false "空间ID筛选" @Param page query int false "页码" default(1) @Param page_size query int false "每页数量" default(20) @Success 200 {object} map[string]interface{} "搜索结果" @Failure 403 {object} errors.AppError "权限不足" @Security Bearer @Security ApiKeyAuth @Router /tenants/search [get]

func (*TenantHandler) UpdateAPIKey

func (h *TenantHandler) UpdateAPIKey(c *gin.Context)

UpdateAPIKey 修改已创建租户 API Key 的授权范围和其他可配置属性。 路由层要求当前租户 Owner;字段校验与创建接口保持一致。

func (*TenantHandler) UpdateAPIPrincipalConfig

func (h *TenantHandler) UpdateAPIPrincipalConfig(c *gin.Context)

UpdateAPIPrincipalConfig godoc @Summary 更新空间 API Key 用户身份配置 @Description 配置 X-API-Key 请求如何映射为终端 Principal(Owner) @Tags 空间管理 @Accept json @Produce json @Param id path int true "空间ID" @Param request body handler.apiPrincipalConfigRequest true "API principal 配置" @Success 200 {object} map[string]interface{} "更新后的配置" @Failure 400 {object} errors.AppError "请求参数错误" @Failure 403 {object} errors.AppError "权限不足" @Security Bearer @Router /tenants/{id}/api-principal-config [put]

func (*TenantHandler) UpdateTenant

func (h *TenantHandler) UpdateTenant(c *gin.Context)

UpdateTenant godoc @Summary 更新空间 @Description 更新空间信息 @Tags 空间管理 @Accept json @Produce json @Param id path int true "空间ID" @Param request body types.Tenant true "空间信息" @Success 200 {object} map[string]interface{} "更新后的空间" @Failure 400 {object} errors.AppError "请求参数错误" @Security Bearer @Router /tenants/{id} [put]

func (*TenantHandler) UpdateTenantKV

func (h *TenantHandler) UpdateTenantKV(c *gin.Context)

UpdateTenantKV godoc @Summary 更新空间KV配置 @Description 更新空间级别的KV配置(支持web-search-config、parser-engine-config、storage-engine-config、chat-history-config、retrieval-config) @Tags 空间管理 @Accept json @Produce json @Param key path string true "配置键名" @Param request body object true "配置值" @Success 200 {object} map[string]interface{} "更新成功" @Failure 400 {object} errors.AppError "不支持的键" @Security Bearer @Security ApiKeyAuth @Router /tenants/kv/{key} [put]

type TenantInvitationHandler

type TenantInvitationHandler struct {
	// contains filtered or unexported fields
}

TenantInvitationHandler exposes the tenant-scoped CRUD on the `tenant_invitations` table plus the user-self-service inbox endpoints (/me/invitations*). Route-level RBAC: tenant routes are Owner-gated (POST/DELETE) or Viewer-gated (GET); inbox routes only require authentication (the service enforces "only invitee can act").

func NewTenantInvitationHandler

func NewTenantInvitationHandler(
	invitationService interfaces.TenantInvitationService,
	userService interfaces.UserService,
	tenantService interfaces.TenantService,
	memberService interfaces.TenantMemberService,
	systemSettingSvc interfaces.SystemSettingService,
	configInfo *config.Config,
) *TenantInvitationHandler

NewTenantInvitationHandler wires the dependencies. tenantService hydrates tenant names in the inbox view; configInfo supplies FrontendBaseURL for share-link URL composition. memberService + systemSettingSvc back the auto-accept switch (tenant.auto_accept_invitation); both are nil-guarded for tests (production wiring always injects both).

func (*TenantInvitationHandler) AcceptMyInvitation

func (h *TenantInvitationHandler) AcceptMyInvitation(c *gin.Context)

AcceptMyInvitation godoc @Summary 接受邀请 @Description 当前登录用户接受一条 pending 邀请;服务端会同时写入 tenant_members 行。 @Tags 我的邀请 @Produce json @Param inv_id path string true "邀请 ID" @Success 200 {object} map[string]interface{} @Security Bearer @Router /me/invitations/{inv_id}/accept [post]

func (*TenantInvitationHandler) AcceptMyInvitationByToken

func (h *TenantInvitationHandler) AcceptMyInvitationByToken(c *gin.Context)

AcceptMyInvitationByToken godoc @Summary 通过共享链接加入空间 @Description 已登录用户用共享邀请链接 token 加入空间,不创建新账号;对已是成员的用户幂等。 @Tags 我的邀请 @Accept json @Produce json @Param request body acceptInvitationByTokenRequest true "邀请 token" @Success 200 {object} map[string]interface{} @Failure 410 {object} apperrors.AppError "链接无效或已撤销" @Security Bearer @Router /me/invitations/accept-by-token [post]

func (*TenantInvitationHandler) CountMyPendingInvitations

func (h *TenantInvitationHandler) CountMyPendingInvitations(c *gin.Context)

CountMyPendingInvitations godoc @Summary 获取我的待处理邀请数 @Description 轻量级 endpoint,返回当前登录用户的 pending 邀请数,用于头像旁的角标轮询。 @Tags 我的邀请 @Produce json @Success 200 {object} map[string]interface{} @Security Bearer @Router /me/invitations/pending-count [get]

func (*TenantInvitationHandler) CreateInvitation

func (h *TenantInvitationHandler) CreateInvitation(c *gin.Context)

CreateInvitation godoc @Summary 发出空间邀请 @Description Owner 通过邮箱邀请已注册用户加入空间。开启 tenant.auto_accept_invitation 后被邀请人立即自动加入(响应为成员结构),否则需在 /me/invitations 接受后成为成员。 @Tags 空间邀请 @Accept json @Produce json @Param id path string true "空间 ID" @Param request body createInvitationRequest true "邀请请求" @Success 201 {object} map[string]interface{} @Security Bearer @Router /tenants/{id}/invitations [post]

func (h *TenantInvitationHandler) CreateInviteLink(c *gin.Context)

CreateInviteLink godoc @Summary 生成共享邀请链接 @Description 生成一条多次使用的共享邀请链接:谁拿到链接谁就能注册并加入当前空间。 @Description 链接持续有效,直到过期或被撤销。 @Tags 空间邀请 @Accept json @Produce json @Param id path string true "空间 ID" @Param request body createInviteLinkRequest true "共享链接配置" @Success 201 {object} map[string]interface{} @Security Bearer @Router /tenants/{id}/invite-links [post]

func (*TenantInvitationHandler) DeclineMyInvitation

func (h *TenantInvitationHandler) DeclineMyInvitation(c *gin.Context)

DeclineMyInvitation godoc @Summary 拒绝邀请 @Description 当前登录用户拒绝一条 pending 邀请;不创建 tenant_members 行。 @Tags 我的邀请 @Produce json @Param inv_id path string true "邀请 ID" @Success 200 {object} map[string]interface{} @Security Bearer @Router /me/invitations/{inv_id}/decline [post]

func (*TenantInvitationHandler) ListMyInvitations

func (h *TenantInvitationHandler) ListMyInvitations(c *gin.Context)

ListMyInvitations godoc @Summary 列出我的待接受邀请 @Description 返回当前登录用户的待接受邀请(默认仅 pending),用于头像入口和 /invitations 收件箱页。 @Tags 我的邀请 @Produce json @Param include_terminal query bool false "是否包含已处理 / 已过期等终止态行(默认 false)" @Success 200 {object} map[string]interface{} @Security Bearer @Router /me/invitations [get]

func (*TenantInvitationHandler) ListTenantInvitations

func (h *TenantInvitationHandler) ListTenantInvitations(c *gin.Context)

ListTenantInvitations godoc @Summary 列出空间邀请 @Description 按空间列出待接受 / 历史邀请。query include_terminal=true 时附带 accepted/declined/revoked/expired。 @Tags 空间邀请 @Produce json @Param id path string true "空间 ID" @Param include_terminal query bool false "是否包含终止态行(默认 false)" @Param page query int false "页码(从 1 起)" default(1) @Param page_size query int false "每页数量" default(20) @Success 200 {object} map[string]interface{} @Security Bearer @Router /tenants/{id}/invitations [get]

func (*TenantInvitationHandler) RevokeInvitation

func (h *TenantInvitationHandler) RevokeInvitation(c *gin.Context)

RevokeInvitation godoc @Summary 撤销待接受邀请 @Description Owner 取消一条还在 pending 的邀请;已 accepted/declined/revoked/expired 的行不可再撤销。 @Tags 空间邀请 @Produce json @Param id path string true "空间 ID" @Param inv_id path string true "邀请 ID" @Success 200 {object} map[string]interface{} @Security Bearer @Router /tenants/{id}/invitations/{inv_id} [delete]

type TenantMemberHandler

type TenantMemberHandler struct {
	// contains filtered or unexported fields
}

TenantMemberHandler exposes /tenants/:id/members CRUD. The route layer enforces RBAC (Viewer for list, Owner for any mutation) — see router.RegisterTenantRoutes — so we don't re-check role here.

Tenant scoping: the auth middleware resolves the caller's role against the *active* tenant (JWT / X-Tenant-ID switch / API-key). The URL :id is independent and MUST be cross-checked: a user who is Owner of tenant A could otherwise POST /tenants/B/members and have the role gate happily accept their tenant-A role for an operation that targets tenant B. That cross-check now lives in middleware.RequirePathTenantMatch (mounted at the /tenants/:id route group); by the time a request reaches one of the methods below, :id is guaranteed to either match the active tenant or carry a cross-tenant superuser bypass.

func NewTenantMemberHandler

func NewTenantMemberHandler(
	memberService interfaces.TenantMemberService,
	userService interfaces.UserService,
) *TenantMemberHandler

NewTenantMemberHandler wires the dependencies. PR 1 already provides both services through the dig container; we just consume them. The previous *config.Config argument was removed once middleware.RequirePathTenantMatch took over the cross-tenant superuser carve-out.

func (*TenantMemberHandler) AddMember

func (h *TenantMemberHandler) AddMember(c *gin.Context)

AddMember godoc @Summary 直接添加空间成员(直加路径) @Description

Owner 通过 email 直接把用户作为 active 成员添加进当前空间。

这是【直加路径】,被加入的用户没有任何确认机会就出现在空间里——
保留它是为了三类不需要走邀请确认的场景:
  1. 自动化脚本 / 平台运维 / 数据迁移;
  2. 跨空间超管 (CanAccessAllTenants) 的批量编排;
  3. 对接外部 IdP 时由身份源单向同步成员。

所有由 UI 触发的「邀请伙伴加入」交互应改走
POST /tenants/:id/invitations,那条路径会先创建 pending 行,让被邀请
人在 /me/invitations 主动接受后再写 tenant_members 行(PR #1303 后续)。
这条路径与 invitations 路径共存而不互相替代。

@Tags 空间成员 @Accept json @Produce json @Param id path string true "空间 ID" @Param request body addMemberRequest true "邀请请求" @Success 201 {object} map[string]interface{} @Security Bearer @Router /tenants/{id}/members [post]

func (*TenantMemberHandler) LeaveTenant

func (h *TenantMemberHandler) LeaveTenant(c *gin.Context)

LeaveTenant godoc @Summary 退出当前空间 @Description 调用方主动退出当前空间。等价于以自己的 user_id 调 RemoveMember,

但不需要 Owner 权限——非 Owner 也可以自助离开。最后一位 Owner 仍然不能离开
(需先把其他成员提升为 Owner),由服务层 ErrLastOwner 拦截。

@Tags 空间成员 @Produce json @Param id path string true "空间 ID" @Success 200 {object} map[string]interface{} @Security Bearer @Router /tenants/{id}/leave [post]

func (*TenantMemberHandler) ListMembers

func (h *TenantMemberHandler) ListMembers(c *gin.Context)

ListMembers godoc @Summary 列出空间成员 @Description 分页返回当前空间内 active 成员(含每位成员的角色、邮箱、头像);支持 q 按邮箱/用户名筛选 @Tags 空间成员 @Produce json @Param id path string true "空间 ID" @Param q query string false "按邮箱/用户名模糊筛选" @Param page query int false "页码(从 1 起)" default(1) @Param page_size query int false "每页数量(最大 100)" default(20) @Success 200 {object} map[string]interface{} @Security Bearer @Router /tenants/{id}/members [get]

func (*TenantMemberHandler) RemoveMember

func (h *TenantMemberHandler) RemoveMember(c *gin.Context)

RemoveMember godoc @Summary 移除空间成员 @Description Owner 将某位成员从当前空间中移除(软删除 tenant_members 行);不能移除最后一位 Owner @Tags 空间成员 @Produce json @Param id path string true "空间 ID" @Param user_id path string true "用户 ID" @Success 200 {object} map[string]interface{} @Security Bearer @Router /tenants/{id}/members/{user_id} [delete]

func (*TenantMemberHandler) UpdateMemberRole

func (h *TenantMemberHandler) UpdateMemberRole(c *gin.Context)

UpdateMemberRole godoc @Summary 修改空间成员角色 @Description Owner 修改某位成员在当前空间内的角色;不能将最后一位 Owner 降级 @Tags 空间成员 @Accept json @Produce json @Param id path string true "空间 ID" @Param user_id path string true "用户 ID" @Param request body updateMemberRoleRequest true "目标角色" @Success 200 {object} map[string]interface{} @Security Bearer @Router /tenants/{id}/members/{user_id} [put]

type TestProviderRequest

type TestProviderRequest struct {
	Provider   string                            `json:"provider" binding:"required"`
	Parameters types.WebSearchProviderParameters `json:"parameters"`
}

TestProviderRequest defines the body for testing raw credentials

type TestStoreRequest

type TestStoreRequest struct {
	EngineType       types.RetrieverEngineType `json:"engine_type" binding:"required"`
	ConnectionConfig types.ConnectionConfig    `json:"connection_config" binding:"required"`
}

TestStoreRequest defines the body for testing raw credentials

type TextRelationExtractionRequest

type TextRelationExtractionRequest struct {
	Text    string   `json:"text"     binding:"required"`
	Tags    []string `json:"tags"     binding:"required"`
	ModelID string   `json:"model_id" binding:"required"`
}

TextRelationExtractionRequest 文本关系提取请求结构

type TextRelationExtractionResponse

type TextRelationExtractionResponse struct {
	Nodes     []*types.GraphNode     `json:"nodes"`
	Relations []*types.GraphRelation `json:"relations"`
}

TextRelationExtractionResponse 文本关系提取响应结构

type UpdateAgentRequest

type UpdateAgentRequest struct {
	Name        string `json:"name"`
	Description string `json:"description"`
	// Avatar travels as a pointer so an omitted field can be told apart from
	// an explicit clear: nil keeps the stored avatar, a pointer to "" wipes
	// it. As a plain string the two cases were indistinguishable, so a caller
	// that PUT only a config silently zeroed the avatar and still got a 200.
	Avatar *string                 `json:"avatar"`
	Config types.CustomAgentConfig `json:"config"`
}

UpdateAgentRequest defines the request body for updating an agent

type UpdateChunkRequest

type UpdateChunkRequest struct {
	Content          *string `json:"content"`
	IsEnabled        *bool   `json:"is_enabled"`
	ExpectedRevision *int    `json:"expected_revision"`
}

UpdateChunkRequest defines the request structure for updating a chunk

type UpdateKnowledgeBaseRequest

type UpdateKnowledgeBaseRequest struct {
	Name        string                     `json:"name"        binding:"required"`
	Description string                     `json:"description"`
	Config      *types.KnowledgeBaseConfig `json:"config"`
	// VLMConfig updates the knowledge base's multimodal (vision) config.
	// Optional: nil means "no change", mirroring how CreateKnowledgeBase
	// accepts a top-level vlm_config.
	VLMConfig *types.VLMConfig `json:"vlm_config"`
}

UpdateKnowledgeBaseRequest defines the request body structure for updating a knowledge base

type UpdateKnowledgeRequest

type UpdateKnowledgeRequest struct {
	Title          *string         `json:"title"`
	Description    *string         `json:"description"`
	CustomMetadata json.RawMessage `json:"custom_metadata"`
}

UpdateKnowledgeRequest defines the partial-update body for PUT /knowledge/:id. Omitted fields are left unchanged; an explicit empty description clears the summary.

type UpdateModelRequest

type UpdateModelRequest struct {
	Name        string                `json:"name"`
	DisplayName *string               `json:"display_name"`
	Description string                `json:"description"`
	Parameters  types.ModelParameters `json:"parameters"`
	Source      types.ModelSource     `json:"source"`
	Type        types.ModelType       `json:"type"`
}

UpdateModelRequest defines the structure for model update requests Contains fields that can be updated for an existing model

type UpdateProviderRequest

type UpdateProviderRequest struct {
	Name        string                            `json:"name"`
	Description string                            `json:"description"`
	Parameters  types.WebSearchProviderParameters `json:"parameters"`
	IsDefault   bool                              `json:"is_default"`
}

UpdateProviderRequest defines the request body for updating a provider

type UpdateStoreRequest

type UpdateStoreRequest struct {
	Name string `json:"name" binding:"required"`
}

UpdateStoreRequest defines the request body for updating a vector store. Only name is mutable — engine_type, connection_config, index_config are immutable.

type UpdateSystemSettingRequest

type UpdateSystemSettingRequest struct {
	// Value is intentionally `any` (decoded as float64 / string / bool /
	// etc. by the JSON unmarshaller). Service.encodeForType normalises
	// these against the registry's declared type and rejects mismatches.
	Value any `json:"value"`
}

UpdateSystemSettingRequest is the body for PUT /system/admin/settings/:key. `value` carries the new value as raw JSON — int / string / bool depending on the registry-declared value_type. The service validates the type strictly and rejects mismatches with 400.

type UpsertGeneratedQuestionRequest

type UpsertGeneratedQuestionRequest struct {
	QuestionID string `json:"question_id"`
	Question   string `json:"question" binding:"required"`
}

type UserResourceFavoriteHandler

type UserResourceFavoriteHandler struct {
	// contains filtered or unexported fields
}

UserResourceFavoriteHandler exposes the per-user starred-resource API.

Authorization model: a user can only manipulate *their own* favorites in the tenant they're currently scoped into (TenantIDContextKey from the auth middleware). Cross-user or cross-tenant access is not allowed — callers cannot pass a user_id or tenant_id query param. This matches the data-model rationale: favorites are personal navigation aids, not shareable resources, so there's no value in admin-style listing.

func (*UserResourceFavoriteHandler) AddFavorite

func (h *UserResourceFavoriteHandler) AddFavorite(c *gin.Context)

AddFavorite godoc @Summary Star a resource @Tags User @Param body body AddFavoriteRequest true "Type + id" @Success 200 {object} map[string]interface{} @Router /user/favorites [post]

func (*UserResourceFavoriteHandler) ListFavorites

func (h *UserResourceFavoriteHandler) ListFavorites(c *gin.Context)

ListFavorites godoc @Summary List my favorites @Description Lists this user's starred resources in the current workspace for a given type @Tags User @Param type query string true "Resource type (kb | agent)" @Success 200 {object} map[string]interface{} @Router /user/favorites [get]

func (*UserResourceFavoriteHandler) RemoveFavorite

func (h *UserResourceFavoriteHandler) RemoveFavorite(c *gin.Context)

RemoveFavorite godoc @Summary Unstar a resource @Tags User @Param type path string true "Resource type" @Param id path string true "Resource id" @Success 200 {object} map[string]interface{} @Router /user/favorites/{type}/{id} [delete]

type VectorStoreHandler

type VectorStoreHandler struct {
	// contains filtered or unexported fields
}

VectorStoreHandler handles HTTP requests for vector store CRUD

func NewVectorStoreHandler

func NewVectorStoreHandler(
	repo interfaces.VectorStoreRepository,
	service interfaces.VectorStoreService,
) *VectorStoreHandler

NewVectorStoreHandler creates a new handler

func (*VectorStoreHandler) CreateStore

func (h *VectorStoreHandler) CreateStore(c *gin.Context)

CreateStore godoc @Summary Create vector store @Description Create a new vector store configuration for the current workspace @Tags VectorStore @Accept json @Produce json @Param request body CreateStoreRequest true "Vector store configuration" @Success 201 {object} map[string]interface{} "Created vector store" @Failure 400 {object} errors.AppError "Invalid request or validation error" @Failure 401 {object} map[string]interface{} "Unauthorized" @Failure 409 {object} errors.AppError "Duplicate endpoint and index" @Security Bearer @Security ApiKeyAuth @Router /vector-stores [post]

func (*VectorStoreHandler) DeleteStore

func (h *VectorStoreHandler) DeleteStore(c *gin.Context)

DeleteStore godoc @Summary Delete vector store @Description Soft-delete a vector store. Env stores cannot be deleted. @Tags VectorStore @Produce json @Param id path string true "Vector store ID" @Success 200 {object} map[string]interface{} "Deletion success" @Failure 400 {object} map[string]interface{} "Env store cannot be deleted" @Failure 401 {object} map[string]interface{} "Unauthorized" @Failure 404 {object} map[string]interface{} "Vector store not found" @Security Bearer @Security ApiKeyAuth @Router /vector-stores/{id} [delete]

func (*VectorStoreHandler) GetStore

func (h *VectorStoreHandler) GetStore(c *gin.Context)

GetStore godoc @Summary Get vector store @Description Retrieve a single vector store by ID. Supports both DB stores and env stores (__env_* IDs) @Tags VectorStore @Produce json @Param id path string true "Vector store ID" @Success 200 {object} map[string]interface{} "Vector store details" @Failure 401 {object} map[string]interface{} "Unauthorized" @Failure 404 {object} map[string]interface{} "Vector store not found" @Security Bearer @Security ApiKeyAuth @Router /vector-stores/{id} [get]

func (*VectorStoreHandler) ListStoreTypes

func (h *VectorStoreHandler) ListStoreTypes(c *gin.Context)

ListStoreTypes godoc @Summary List vector store types @Description Return supported engine types with connection and index field schemas for UI form generation @Tags VectorStore @Produce json @Success 200 {object} map[string]interface{} "List of engine types with config schemas" @Router /vector-stores/types [get]

func (*VectorStoreHandler) ListStores

func (h *VectorStoreHandler) ListStores(c *gin.Context)

ListStores godoc @Summary List vector stores @Description List all vector stores for the current workspace, including environment-configured and user-created stores @Tags VectorStore @Produce json @Success 200 {object} map[string]interface{} "List of vector stores (env + DB)" @Failure 401 {object} map[string]interface{} "Unauthorized" @Security Bearer @Security ApiKeyAuth @Router /vector-stores [get]

func (*VectorStoreHandler) TestStoreByID

func (h *VectorStoreHandler) TestStoreByID(c *gin.Context)

TestStoreByID godoc @Summary Test vector store connection by ID @Description Test connectivity of an existing saved or env store. Returns detected server version. For DB stores, the version is automatically saved to connection_config. @Tags VectorStore @Produce json @Param id path string true "Vector store ID" @Success 200 {object} map[string]interface{} "Connection test result (success, version)" @Failure 401 {object} map[string]interface{} "Unauthorized" @Failure 404 {object} map[string]interface{} "Vector store not found" @Security Bearer @Security ApiKeyAuth @Router /vector-stores/{id}/test [post]

func (*VectorStoreHandler) TestStoreRaw

func (h *VectorStoreHandler) TestStoreRaw(c *gin.Context)

TestStoreRaw godoc @Summary Test vector store connection with raw credentials @Description Test connectivity using provided credentials without persisting. Returns detected server version. @Tags VectorStore @Accept json @Produce json @Param request body TestStoreRequest true "Engine type and connection config" @Success 200 {object} map[string]interface{} "Connection test result (success, version)" @Failure 400 {object} errors.AppError "Invalid request" @Failure 401 {object} map[string]interface{} "Unauthorized" @Security Bearer @Security ApiKeyAuth @Router /vector-stores/test [post]

func (*VectorStoreHandler) UpdateStore

func (h *VectorStoreHandler) UpdateStore(c *gin.Context)

UpdateStore godoc @Summary Update vector store @Description Update a vector store (name only). Engine type, connection config, and index config are immutable. Env stores cannot be modified. @Tags VectorStore @Accept json @Produce json @Param id path string true "Vector store ID" @Param request body UpdateStoreRequest true "Updated fields" @Success 200 {object} map[string]interface{} "Updated vector store" @Failure 400 {object} map[string]interface{} "Env store or validation error" @Failure 401 {object} map[string]interface{} "Unauthorized" @Failure 404 {object} map[string]interface{} "Vector store not found" @Security Bearer @Security ApiKeyAuth @Router /vector-stores/{id} [put]

type WeKnoraCloudHandler

type WeKnoraCloudHandler struct {
	// contains filtered or unexported fields
}

WeKnoraCloudHandler 处理 WeKnoraCloud 凭证管理

func NewWeKnoraCloudHandler

func NewWeKnoraCloudHandler(svc interfaces.WeKnoraCloudService) *WeKnoraCloudHandler

NewWeKnoraCloudHandler 构造函数

func (*WeKnoraCloudHandler) SaveCredentials

func (h *WeKnoraCloudHandler) SaveCredentials(c *gin.Context)

SaveCredentials POST /api/v1/weknoracloud/credentials 仅保存 APPID/APPSECRET 凭证到空间配置,不自动创建模型

SaveCredentials godoc @Summary 保存 WeKnoraCloud 凭证 @Description 保存 APPID/APPSECRET 到当前空间配置(不自动创建模型) @Tags WeKnoraCloud @Accept json @Produce json @Param request body map[string]interface{} true "{app_id, app_secret}" @Success 200 {object} map[string]interface{} "success: true" @Failure 400 {object} map[string]interface{} "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /weknoracloud/credentials [post]

func (*WeKnoraCloudHandler) Status

func (h *WeKnoraCloudHandler) Status(c *gin.Context)

Status GET /api/v1/models/weknoracloud/status 检查当前空间的 WeKnoraCloud 凭证是否完好,如需重新初始化则返回 needs_reinit=true

Status godoc @Summary 检查 WeKnoraCloud 凭证状态 @Description 检查当前空间的 WeKnoraCloud 凭证是否完好;needs_reinit=true 表示需要重新保存 @Tags WeKnoraCloud @Produce json @Success 200 {object} map[string]interface{} "凭证状态" @Failure 500 {object} map[string]interface{} "服务器错误" @Security Bearer @Security ApiKeyAuth @Router /models/weknoracloud/status [get]

type WebSearchHandler

type WebSearchHandler struct{}

WebSearchHandler handles legacy web search related requests

func NewWebSearchHandler

func NewWebSearchHandler() *WebSearchHandler

NewWebSearchHandler creates a new web search handler

func (*WebSearchHandler) GetProviders

func (h *WebSearchHandler) GetProviders(c *gin.Context)

GetProviders returns the list of available web search provider types.

GetProviders godoc @Summary 获取可用网络搜索 Provider 列表 @Description 返回所有已注册的网络搜索 provider(含元数据) @Tags 网络搜索 @Produce json @Success 200 {object} map[string]interface{} "provider 列表" @Security Bearer @Security ApiKeyAuth @Router /web-search/providers [get]

type WebSearchProviderCredentialsHandler

type WebSearchProviderCredentialsHandler struct {
	// contains filtered or unexported fields
}

WebSearchProviderCredentialsHandler handles credentials for web search providers via the dedicated /credentials subresource. Currently the only recognized field is "api_key" — every provider that needs credentials uses just one key (Bing / Google / Tavily / Ollama / Baidu), and DuckDuckGo / SearXNG don't need credentials at all.

func (*WebSearchProviderCredentialsHandler) DeleteField

func (h *WebSearchProviderCredentialsHandler) DeleteField(c *gin.Context)

func (*WebSearchProviderCredentialsHandler) Put

type WebSearchProviderHandler

type WebSearchProviderHandler struct {
	// contains filtered or unexported fields
}

WebSearchProviderHandler handles HTTP requests for web search provider CRUD

func NewWebSearchProviderHandler

NewWebSearchProviderHandler creates a new handler

func (*WebSearchProviderHandler) CreateProvider

func (h *WebSearchProviderHandler) CreateProvider(c *gin.Context)

CreateProvider creates a new web search provider

func (*WebSearchProviderHandler) DeleteProvider

func (h *WebSearchProviderHandler) DeleteProvider(c *gin.Context)

DeleteProvider deletes a web search provider.

DeleteProvider godoc @Summary 删除网络搜索 Provider @Description 删除指定 provider 配置 @Tags 网络搜索 @Produce json @Param id path string true "Provider ID" @Success 200 {object} map[string]interface{} "success: true" @Failure 404 {object} map[string]interface{} "Provider 不存在" @Security Bearer @Security ApiKeyAuth @Router /web-search-providers/{id} [delete]

func (*WebSearchProviderHandler) GetProvider

func (h *WebSearchProviderHandler) GetProvider(c *gin.Context)

GetProvider retrieves a single web search provider by ID.

GetProvider godoc @Summary 获取网络搜索 Provider 详情 @Description 根据 ID 获取指定 provider 配置 @Tags 网络搜索 @Produce json @Param id path string true "Provider ID" @Success 200 {object} types.WebSearchProviderEntity "Provider 详情" @Failure 404 {object} map[string]interface{} "Provider 不存在" @Security Bearer @Security ApiKeyAuth @Router /web-search-providers/{id} [get]

func (*WebSearchProviderHandler) ListProviderTypes

func (h *WebSearchProviderHandler) ListProviderTypes(c *gin.Context)

ListProviderTypes returns available provider types and their parameter requirements.

ListProviderTypes godoc @Summary 获取网络搜索 Provider 类型元数据 @Description 返回 UI 表单需要的 provider 类型及参数定义 @Tags 网络搜索 @Produce json @Success 200 {object} map[string]interface{} "provider 类型列表" @Security Bearer @Security ApiKeyAuth @Router /web-search-providers/types [get]

func (*WebSearchProviderHandler) ListProviders

func (h *WebSearchProviderHandler) ListProviders(c *gin.Context)

ListProviders lists all web search providers for the current tenant

func (*WebSearchProviderHandler) TestProviderByID

func (h *WebSearchProviderHandler) TestProviderByID(c *gin.Context)

TestProviderByID tests an existing saved provider by performing a sample search.

TestProviderByID godoc @Summary 测试已保存的 Provider @Description 使用数据库中已保存的凭证测试连通性 @Tags 网络搜索 @Produce json @Param id path string true "Provider ID" @Success 200 {object} map[string]interface{} "测试结果" @Failure 404 {object} map[string]interface{} "Provider 不存在" @Security Bearer @Security ApiKeyAuth @Router /web-search-providers/{id}/test [post]

func (*WebSearchProviderHandler) TestProviderRaw

func (h *WebSearchProviderHandler) TestProviderRaw(c *gin.Context)

TestProviderRaw tests a provider with raw credentials (no persistence).

TestProviderRaw godoc @Summary 使用原始凭证测试 Provider(不落库) @Description 使用前端表单中尚未保存的凭证测试连通性,用于"测试连接"按钮 @Tags 网络搜索 @Accept json @Produce json @Param request body handler.TestProviderRequest true "{provider, parameters}" @Success 200 {object} map[string]interface{} "测试结果" @Failure 400 {object} map[string]interface{} "请求参数错误" @Security Bearer @Security ApiKeyAuth @Router /web-search-providers/test [post]

func (*WebSearchProviderHandler) UpdateProvider

func (h *WebSearchProviderHandler) UpdateProvider(c *gin.Context)

UpdateProvider updates a web search provider.

UpdateProvider godoc @Summary 更新网络搜索 Provider @Description 更新指定 provider 的名称/描述/参数/是否默认 @Tags 网络搜索 @Accept json @Produce json @Param id path string true "Provider ID" @Param request body handler.UpdateProviderRequest true "更新字段" @Success 200 {object} types.WebSearchProviderEntity "更新后的 Provider" @Failure 400 {object} map[string]interface{} "请求参数错误" @Failure 404 {object} map[string]interface{} "Provider 不存在" @Security Bearer @Security ApiKeyAuth @Router /web-search-providers/{id} [put]

type WikiPageHandler

type WikiPageHandler struct {
	// contains filtered or unexported fields
}

WikiPageHandler handles HTTP requests for wiki page operations

func NewWikiPageHandler

func NewWikiPageHandler(
	wikiService interfaces.WikiPageService,
	kbService interfaces.KnowledgeBaseService,
	lintService *service.WikiLintService,
	auditService interfaces.AuditLogService,
	memoryService interfaces.MemoryService,
) *WikiPageHandler

NewWikiPageHandler creates a new wiki page handler

func (*WikiPageHandler) AutoFix

func (h *WikiPageHandler) AutoFix(c *gin.Context)

AutoFix godoc @Summary Auto-fix wiki issues @Description Automatically fix fixable wiki issues (broken links, etc.) @Tags Wiki @Produce json @Param kb_id path string true "Knowledge base ID" @Success 200 {object} map[string]interface{} @Security Bearer @Router /knowledgebase/{kb_id}/wiki/auto-fix [post]

func (*WikiPageHandler) CreateFolder

func (h *WikiPageHandler) CreateFolder(c *gin.Context)

CreateFolder godoc @Summary Create a wiki folder @Description Create a new (initially empty) directory node under parent_id @Tags Wiki @Accept json @Produce json @Param kb_id path string true "Knowledge base ID" @Param folder body types.WikiFolderCreateRequest true "Folder data" @Success 201 {object} types.WikiFolder @Failure 400 {object} errors.AppError @Failure 409 {object} errors.AppError @Security Bearer @Router /knowledgebase/{kb_id}/wiki/folders [post]

func (*WikiPageHandler) CreatePage

func (h *WikiPageHandler) CreatePage(c *gin.Context)

CreatePage godoc @Summary Create a wiki page @Description Create a new wiki page in the knowledge base @Tags Wiki @Accept json @Produce json @Param kb_id path string true "Knowledge base ID" @Param page body types.WikiPage true "Wiki page data" @Success 201 {object} types.WikiPage @Failure 400 {object} errors.AppError @Security Bearer @Router /knowledgebase/{kb_id}/wiki/pages [post]

func (*WikiPageHandler) DeleteFolder

func (h *WikiPageHandler) DeleteFolder(c *gin.Context)

DeleteFolder godoc @Summary Delete an empty wiki folder @Description Delete a folder that has no pages and no child folders @Tags Wiki @Param kb_id path string true "Knowledge base ID" @Param folder_id path string true "Folder ID" @Success 204 @Failure 400 {object} errors.AppError @Failure 404 {object} errors.AppError @Security Bearer @Router /knowledgebase/{kb_id}/wiki/folders/{folder_id} [delete]

func (*WikiPageHandler) DeletePage

func (h *WikiPageHandler) DeletePage(c *gin.Context)

DeletePage godoc @Summary Delete a wiki page @Description Soft-delete a wiki page by slug @Tags Wiki @Param kb_id path string true "Knowledge base ID" @Param slug path string true "Page slug" @Success 204 @Failure 404 {object} errors.AppError @Security Bearer @Router /knowledgebase/{kb_id}/wiki/pages/{slug} [delete]

func (*WikiPageHandler) GetGraph

func (h *WikiPageHandler) GetGraph(c *gin.Context)

GetGraph godoc @Summary Get wiki link graph @Description Returns a slice of the wiki link graph for visualization. Supports @Description `mode=overview` (top-N most-connected pages, default) and @Description `mode=ego` (BFS neighborhood of a center slug) to keep response @Description size tractable for knowledge bases with tens of thousands of pages. @Tags Wiki @Produce json @Param kb_id path string true "Knowledge base ID" @Param mode query string false "overview (default) | ego" @Param center query string false "Center slug for ego mode" @Param depth query int false "Ego BFS depth (1-3, default 1)" @Param types query string false "Comma-separated page_type allow-list" @Param limit query int false "Max nodes to return (default 500, max 2000)" @Success 200 {object} types.WikiGraphData @Security Bearer @Router /knowledgebase/{kb_id}/wiki/graph [get]

func (*WikiPageHandler) GetIndex

func (h *WikiPageHandler) GetIndex(c *gin.Context)

GetIndex godoc @Summary Get wiki index view @Description Returns the wiki index as intro text plus per-type paginated @Description directory groups. The heavy directory markdown that used to @Description live in wiki_pages.content was replaced with this structured @Description response so a KB with tens of thousands of pages no longer @Description materializes megabytes of TEXT on every index open. @Tags Wiki @Produce json @Param kb_id path string true "Knowledge base ID" @Param types query string false "Comma-separated page types (default: all content types)" @Param limit query int false "Per-group window size, 1-200 (default 50)" @Param cursor query string false "Opaque offset cursor from previous response" @Success 200 {object} types.WikiIndexResponse @Security Bearer @Router /knowledgebase/{kb_id}/wiki/index [get]

func (*WikiPageHandler) GetPage

func (h *WikiPageHandler) GetPage(c *gin.Context)

GetPage godoc @Summary Get a wiki page by slug @Description Retrieve a wiki page by its slug, including titles of existing backlinks @Tags Wiki @Produce json @Param kb_id path string true "Knowledge base ID" @Param slug path string true "Page slug" @Success 200 {object} types.WikiPageDetail @Failure 404 {object} errors.AppError @Security Bearer @Router /knowledgebase/{kb_id}/wiki/pages/{slug} [get]

func (*WikiPageHandler) GetStats

func (h *WikiPageHandler) GetStats(c *gin.Context)

GetStats godoc @Summary Get wiki statistics @Description Returns aggregate statistics about the wiki @Tags Wiki @Produce json @Param kb_id path string true "Knowledge base ID" @Success 200 {object} types.WikiStats @Security Bearer @Router /knowledgebase/{kb_id}/wiki/stats [get]

func (*WikiPageHandler) KBCreatorLookupFromKBPath

func (h *WikiPageHandler) KBCreatorLookupFromKBPath(c *gin.Context) (string, error)

KBCreatorLookupFromKBPath resolves :kb_id (used by wiki routes) to KnowledgeBase.CreatorID. No chain hop — the wiki page URL already carries the owning KB id, so we go straight to the KB service. The tenant defence-in-depth re-check stays the same as KBCreatorLookup: repo.GetKnowledgeBaseByID is unscoped, so we explicitly compare against the context tenant.

func (*WikiPageHandler) Lint

func (h *WikiPageHandler) Lint(c *gin.Context)

Lint godoc @Summary Run wiki lint @Description Perform a comprehensive health check on the wiki @Tags Wiki @Produce json @Param kb_id path string true "Knowledge base ID" @Success 200 {object} service.WikiLintReport @Security Bearer @Router /knowledgebase/{kb_id}/wiki/lint [get]

func (*WikiPageHandler) ListFolders

func (h *WikiPageHandler) ListFolders(c *gin.Context)

ListFolders godoc @Summary List wiki folders @Description Retrieve the direct child folders of a parent folder (parent_id empty = root level), each with its page count and a has-children flag for the directory tree. @Tags Wiki @Produce json @Param kb_id path string true "Knowledge base ID" @Param parent_id query string false "Parent folder id (empty = root)" @Success 200 {object} types.WikiFolderListResponse @Failure 400 {object} errors.AppError @Security Bearer @Router /knowledgebase/{kb_id}/wiki/folders [get]

func (*WikiPageHandler) ListIssues

func (h *WikiPageHandler) ListIssues(c *gin.Context)

ListIssues godoc @Summary List wiki page issues @Description List issues flagged on wiki pages with optional filtering @Tags Wiki @Produce json @Param kb_id path string true "Knowledge base ID" @Param slug query string false "Filter by page slug" @Param status query string false "Filter by status (pending, ignored, resolved)" @Success 200 {array} types.WikiPageIssue @Security Bearer @Router /knowledgebase/{kb_id}/wiki/issues [get]

func (*WikiPageHandler) ListPages

func (h *WikiPageHandler) ListPages(c *gin.Context)

ListPages godoc @Summary List wiki pages @Description List wiki pages with optional filtering and pagination @Tags Wiki @Produce json @Param kb_id path string true "Knowledge base ID" @Param page_type query string false "Filter by page type; comma-separated for multiple (e.g. entity,concept)" @Param status query string false "Filter by status" @Param query query string false "Full-text search" @Param page query int false "Page number" @Param page_size query int false "Page size" @Param sort_by query string false "Sort field" @Param sort_order query string false "Sort order (asc/desc)" @Success 200 {object} types.WikiPageListResponse @Failure 400 {object} errors.AppError @Security Bearer @Router /knowledgebase/{kb_id}/wiki/pages [get]

func (*WikiPageHandler) ListRevisions

func (h *WikiPageHandler) ListRevisions(c *gin.Context)

ListRevisions godoc @Summary List wiki page revisions @Description Returns the stored historical snapshots for a page, newest @Description first (content omitted), plus the current version. Passing @Description `version` returns that single snapshot with full content. @Tags Wiki @Produce json @Param kb_id path string true "Knowledge base ID" @Param slug path string true "Page slug" @Param version query int false "Return this single revision with content" @Param limit query int false "Page size (default 50, max 200)" @Param offset query int false "Offset into the newest-first list" @Success 200 {object} types.WikiPageRevisionListResponse @Failure 404 {object} errors.AppError @Security Bearer @Router /knowledgebase/{kb_id}/wiki/revisions/{slug} [get]

func (*WikiPageHandler) MovePage

func (h *WikiPageHandler) MovePage(c *gin.Context)

MovePage godoc @Summary Move a wiki page into a folder @Description Relocate a page (identified by slug in the body) into a folder (folder_id empty = root); the page's cached category path is recomputed @Tags Wiki @Accept json @Produce json @Param kb_id path string true "Knowledge base ID" @Param move body types.WikiPageMoveRequest true "Move target" @Success 200 {object} types.WikiPage @Failure 404 {object} errors.AppError @Security Bearer @Router /knowledgebase/{kb_id}/wiki/move-page [put]

func (h *WikiPageHandler) RebuildLinks(c *gin.Context)

RebuildLinks godoc @Summary Rebuild wiki links @Description Re-parse all pages and rebuild bidirectional link references @Tags Wiki @Param kb_id path string true "Knowledge base ID" @Success 200 {object} map[string]string @Security Bearer @Router /knowledgebase/{kb_id}/wiki/rebuild-links [post]

func (*WikiPageHandler) RevertPage

func (h *WikiPageHandler) RevertPage(c *gin.Context)

RevertPage godoc @Summary Revert a wiki page to an earlier revision @Description Rolls the page (slug in the body, like move-page) back to @Description the content of the given stored revision. Applied as a @Description regular edit: the pre-revert state is snapshotted and the @Description version advances. @Tags Wiki @Accept json @Produce json @Param kb_id path string true "Knowledge base ID" @Param revert body types.WikiPageRevertRequest true "Revert target" @Success 200 {object} types.WikiPage @Failure 400 {object} errors.AppError @Failure 404 {object} errors.AppError @Failure 409 {object} errors.AppError @Security Bearer @Router /knowledgebase/{kb_id}/wiki/revert [post]

func (*WikiPageHandler) SearchPages

func (h *WikiPageHandler) SearchPages(c *gin.Context)

SearchPages godoc @Summary Search wiki pages @Description Full-text search over wiki pages @Tags Wiki @Produce json @Param kb_id path string true "Knowledge base ID" @Param q query string true "Search query" @Param limit query int false "Max results (default 10)" @Success 200 {array} types.WikiPage @Security Bearer @Router /knowledgebase/{kb_id}/wiki/search [get]

func (*WikiPageHandler) SearchPagesAcross

func (h *WikiPageHandler) SearchPagesAcross(c *gin.Context)

SearchPagesAcross godoc @Summary Cross-KB wiki search @Description Cross-KB wiki search using the same POSIX regex ranking as single-KB wiki search @Tags Wiki @Accept json @Produce json @Param request body SearchWikiRequest true "Wiki search request" @Success 200 {object} map[string]interface{} @Failure 400 {object} errors.AppError @Security Bearer @Security ApiKeyAuth @Router /wiki-search [post]

func (*WikiPageHandler) UpdateFolder

func (h *WikiPageHandler) UpdateFolder(c *gin.Context)

UpdateFolder godoc @Summary Rename or move a wiki folder @Description Rename and/or reparent a folder; the whole subtree's paths and the affected pages' cached paths are recomputed @Tags Wiki @Accept json @Produce json @Param kb_id path string true "Knowledge base ID" @Param folder_id path string true "Folder ID" @Param folder body types.WikiFolderUpdateRequest true "Folder update" @Success 200 {object} types.WikiFolder @Failure 400 {object} errors.AppError @Failure 404 {object} errors.AppError @Failure 409 {object} errors.AppError @Security Bearer @Router /knowledgebase/{kb_id}/wiki/folders/{folder_id} [put]

func (*WikiPageHandler) UpdateIssueStatus

func (h *WikiPageHandler) UpdateIssueStatus(c *gin.Context)

UpdateIssueStatus godoc @Summary Update wiki page issue status @Description Update the status of a flagged wiki page issue @Tags Wiki @Accept json @Produce json @Param kb_id path string true "Knowledge base ID" @Param issue_id path string true "Issue ID" @Param status body object true "New status {'status': 'ignored'}" @Success 200 {object} map[string]string @Failure 400 {object} errors.AppError @Security Bearer @Router /knowledgebase/{kb_id}/wiki/issues/{issue_id}/status [put]

func (*WikiPageHandler) UpdatePage

func (h *WikiPageHandler) UpdatePage(c *gin.Context)

UpdatePage godoc @Summary Update a wiki page @Description Partially update a wiki page by slug. Absent fields keep @Description their stored value. When `version` is > 0 it acts as an @Description optimistic-lock guard: a mismatch with the stored version @Description returns 409 together with the current version so the client @Description can reload and re-apply. @Tags Wiki @Accept json @Produce json @Param kb_id path string true "Knowledge base ID" @Param slug path string true "Page slug" @Param page body types.WikiPageUpdateRequest true "Fields to update" @Success 200 {object} types.WikiPage @Failure 400 {object} errors.AppError @Failure 404 {object} errors.AppError @Failure 409 {object} errors.AppError @Security Bearer @Router /knowledgebase/{kb_id}/wiki/pages/{slug} [put]

type WikiSearchHit

type WikiSearchHit struct {
	ID              string            `json:"id"`
	KnowledgeBaseID string            `json:"knowledge_base_id"`
	Slug            string            `json:"slug"`
	Title           string            `json:"title"`
	PageType        string            `json:"page_type"`
	Aliases         types.StringArray `json:"aliases"`
	Summary         string            `json:"summary"`
	MatchSnippet    string            `json:"match_snippet,omitempty"`
}

WikiSearchHit is the slim POST /wiki-search hit. Full page body is on GET /knowledgebase/:kb_id/wiki/pages/*slug.

Directories

Path Synopsis
Package dto holds response shapes for handler responses that need to differ from the persisted GORM model — most notably, response types that must NOT carry secret fields.
Package dto holds response shapes for handler responses that need to differ from the persisted GORM model — most notably, response types that must NOT carry secret fields.
Package session provides RFB (VNC) client-stream parsing for the sandbox desktop relay.
Package session provides RFB (VNC) client-stream parsing for the sandbox desktop relay.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL