types

package
v0.2.4 Latest Latest
Warning

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

Go to latest
Published: Nov 12, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Index

Constants

View Source
const (
	CacheTypeRerunAll                          = 1
	CacheTypeReuseExistingNode                 = 2
	CacheTypeReuseWhenScriptUnchanged          = 3
	CacheTypeReuseWhenScriptAndParamsUnchanged = 4
)
View Source
const (
	// AnalysisStatusRunning 表示分析已被某个调度器接管并正在推进,是恢复扫描的入口状态。
	AnalysisStatusRunning = "running"
	// AnalysisStatusStopping 表示已收到停止请求,等待所属调度器收敛到终态。
	AnalysisStatusStopping = "stopping"
	// AnalysisStatusStopped 是用户停止后的终态。
	AnalysisStatusStopped = "stopped"
	// AnalysisStatusFinished 是正常跑完的终态。
	AnalysisStatusFinished = "finished"
	// AnalysisStatusFailed 是异常终止的终态。
	AnalysisStatusFailed = "failed"
)

analysis.job_status 取值。所有调度器(legacy dag_v1 / node_v1 / dynamic_v2 / dataflow_v3)共用同一套状态字符串,避免各 orchestrator 各自维护一份常量, 导致统一恢复入口在判断 running / stopping 时出现不一致。

View Source
const (
	// SchedulerModeDag 是静态图调度器(internal/dag/scheduler/dag)。
	// 历史空值 / dag_v1 / node_v1 都归一到此。
	SchedulerModeDag = "dag"
	// SchedulerModeDynamic 是动态物化调度器(internal/dag/scheduler/dynamic)。
	SchedulerModeDynamic = "dynamic"
	// SchedulerModeDataflow 是数据流调度器(internal/dag/scheduler/dataflow)。
	SchedulerModeDataflow = "dataflow"
)

analysis.scheduler_mode 取值,标识推进该分析的调度器,同时是 dag/scheduler.Registry 的查找键。名称直接对应具体实现,不再带 V1/V2/V3 后缀。

View Source
const (
	// AnalysisNodeCreationSourceAgent 是 Agent 命令节点(无脚本)。
	AnalysisNodeCreationSourceAgent = "agent"
	// AnalysisNodeCreationSourceScript 是脚本节点(绑定脚本,参数按 io_schema 解析)。
	AnalysisNodeCreationSourceScript = "script"
	// AnalysisNodeCreationSourceScheduler 是 DAG 调度器物化的节点(绑定脚本)。
	AnalysisNodeCreationSourceScheduler = "scheduler"
)

analysis_nodes.creation_source 取值:节点类型只有这三种。

取值在节点创建时由创建方写入,之后不再变化:

  • agent:Agent 会话直接创建的命令型节点(无脚本,run.sh 由 Agent 生成);
  • script:由脚本契约创建的节点(前端独立节点 / create_script_analysis);
  • scheduler:由 DAG 调度器按流程物化的节点(绑定脚本)。
View Source
const (
	PullPolicyAlways       = "Always"
	PullPolicyIfNotPresent = "IfNotPresent"
	PullPolicyNever        = "Never"
)
View Source
const (
	MinUserBottomPanelHeight = 120
	MaxUserBottomPanelHeight = 800
)

底部面板高度的允许区间(px)。前端拖拽分隔条时会实时更新。

View Source
const (
	AppSessionStatusRunning  = "RUNNING"
	AppSessionStatusStopped  = "STOPPED"
	AppSessionStatusFailed   = "FAILED"
	AppSessionStatusCreating = "CREATING"
	AppSessionStatusPending  = "CREATE_PENDING"
)

AppSession 状态常量(AppSession.Status 是字符串列,这里集中定义便于比较)。

View Source
const (
	// AppSessionKindWeb 表示 Web 应用会话:由 ContainerService.CreateAppSessionByTemplate 创建,
	// 容器运行模板命令,前端通过网关路由访问应用页面。
	AppSessionKindWeb = "web"
	// AppSessionKindTerminal 表示终端会话:由终端会话注册表创建(createOrAdopt),
	// 容器以 keep-alive 命令常驻,交互式 shell 由运行时 exec 打开。
	AppSessionKindTerminal = "terminal"
)

AppSession.SessionKind 的取值:区分会话是「Web 应用会话」还是「终端会话」。

注意与「创建者」区分:创建者是 AgentSessionID(0 = UI,>0 = Agent 会话), 生命周期策略是 Persistent(持久会话 / 一次性会话)。

View Source
const DatasetKeyDatabases = "DATABASES"

DatasetKeyDatabases is the dataset_key of the project's default database directory. The dataset is provisioned on demand by the get_project_database_path agent tool and holds reference databases shared by the project's analysis scripts.

View Source
const DefaultLiteratureFilename = "literature.md"

DefaultLiteratureFilename 是文献工作目录下约定的全文文件名。 与 ProjectReport 的 output.md 类似,全文不再存入数据库,而是保存在 <projectDir>/literature/<literatureId>/ 目录下的该文件中。

View Source
const DefaultProjectReportFilename = utils.DefaultProjectReportFilename

DefaultProjectReportFilename 是项目报告工作目录下约定的输出文件名。 它仍然被 LLM 运行时(projectReport 环境)用来定位报告输出文件。 字面量统一定义在 utils(utils.GetProjectReportOutputFile 依赖它),这里只做别名, 避免两处常量各自漂移。

View Source
const MaxUserBottomTabs = 8

MaxUserBottomTabs 是主区域底部面板(终端 / 日志等)允许保存的最大标签数。

View Source
const MaxUserMenuTabs = 16

MaxUserMenuTabs 是主区域标签页配置允许保存的最大数量,超出的按「最近使用」截断。

Variables

View Source
var (
	// Container 已经停止
	ErrContainerAlreadyStopped = errors.New("container already stopped")
)

Functions

func EncodeArticleCursor

func EncodeArticleCursor(c ArticleCursor) string

EncodeArticleCursor encodes an article cursor to an opaque string.

func NormalizeSchedulerMode added in v0.1.4

func NormalizeSchedulerMode(mode string) string

NormalizeSchedulerMode 把持久化的 scheduler_mode 归一化为当前规范名。

历史值(空值 / dag_v1 / dynamic_v2 / dataflow_v3 / node_v1)会被折叠到当前 名称,保证旧数据仍能解析到正确的调度器;未知值一律回退到默认的静态图调度器。

Types

type AISummary added in v0.1.2

type AISummary struct {
	ID int64 `json:"id,string" gorm:"primaryKey;type:bigint;autoIncrement:false"`

	// OwnerID 摘要所属对象的 ID,主要为 Analysis.ID 或 AnalysisNode.ID。
	OwnerID int64 `json:"owner_id,string" gorm:"column:owner_id;type:bigint;index:idx_ai_summaries_owner"`
	// OwnerType 摘要所属对象的类型:analysis 或 analysis_node。
	OwnerType SummaryOwnerType `json:"owner_type" gorm:"column:owner_type;type:varchar(32);index:idx_ai_summaries_owner"`
	// ProjectID 摘要所属项目 ID(t_project.id),创建时由创建者的激活项目推导。
	ProjectID int64  `json:"project_id,string" gorm:"column:project_id;type:bigint;index:idx_ai_summaries_project"`
	Title     string `json:"title" gorm:"column:title;type:varchar(255)"`
	// Content AI 生成的摘要内容。正文不再落库,而是以文件形式存放在
	// GetAISummaryFile(<baseDir>/data/<projectId>/AiSummary/<summaryId>/summary.md)。
	// 读取详情 / 列表时由 aiSummaryService 按需从文件填充;写入(生成、编辑、失败)
	// 由 AISummaryWorker / aiSummaryService 落盘。非持久化字段。
	Content string `json:"content" gorm:"-"`
	// Status 生成状态:生成中 / 生成成功 / 生成失败。
	Status SummaryStatus `json:"status" gorm:"column:status;type:varchar(32);default:generating"`
	// ProfileID 生成该摘要使用的 Agent Profile ID(agent_profiles.id),用于按 ID 解析 Profile。
	// 为 0 时由 AISummaryWorker 回退到内置 summary Profile。
	ProfileID int64 `json:"profile_id,string" gorm:"column:profile_id;type:bigint;index"`
	// Profile 生成该摘要使用的 Agent Profile 展示名(仅用于展示,不参与查询;
	// 为空表示使用内置 summary Profile)。
	Profile string `json:"profile" gorm:"column:profile;type:varchar(64)"`
	// TaskID 生成该摘要的 Agent 任务 ID(agent_tasks 表)。
	TaskID int64 `json:"task_id,string" gorm:"column:task_id;type:bigint;index"`

	CreatedAt time.Time `json:"created_at" gorm:"column:created_at"`
	UpdatedAt time.Time `json:"updated_at" gorm:"column:updated_at"`

	// Prefix 是摘要所属对象输出目录对应的 /data-analysis URL 前缀,便于前端拼接
	// 该输出目录下结果文件的访问地址。非持久化字段,查询时按需填充
	// (见 aiSummaryService.ListAISummariesByOwner)。
	Prefix string `json:"prefix" gorm:"-"`
}

AISummary 存储 AI 为 Analysis 或 AnalysisNode 的 output 内容生成的摘要。

func (*AISummary) BeforeCreate added in v0.1.2

func (t *AISummary) BeforeCreate(_ *gorm.DB) error

func (AISummary) TableName added in v0.1.2

func (AISummary) TableName() string

type AISummaryGeneratePayload added in v0.1.2

type AISummaryGeneratePayload struct {
	SummaryID int64 `json:"summary_id,string"`
}

AISummaryGeneratePayload 是 AISummary 生成请求的 outbox 事件载荷。

type AISummaryInput added in v0.1.2

type AISummaryInput struct {
	// Title 是摘要标题的候选值。
	Title string `json:"title"`
	// ProfileName 是生成该摘要使用的 AgentProfile 展示名(取自摘要记录,为空回退内置 summary Profile)。
	ProfileName string `json:"profile,omitempty"`
	ProfileID   int64  `json:"profile_id,omitempty,string"`
	// SystemPrompt 是用 Profile 模板 + Vars 渲染后的真实系统提示词。
	SystemPrompt string `json:"system_prompt,omitempty"`
	// Vars 是渲染系统提示词模板所用的变量(业务上下文)。
	Vars map[string]any `json:"vars,omitempty"`
	// WorkingDir 是 Agent 执行任务时的工作目录。
	WorkingDir string `json:"working_dir"`
}

AISummaryInput 是生成摘要时交给 LLM 的输入信息,用于前端展示。

type AISummaryStatusEvent added in v0.1.2

type AISummaryStatusEvent struct {
	SummaryID int64            `json:"summary_id,string"`
	OwnerType SummaryOwnerType `json:"owner_type"`
	OwnerID   int64            `json:"owner_id,string"`
	Status    SummaryStatus    `json:"status"`
}

AISummaryStatusEvent 在 AI 摘要状态发生变更时发布到事件总线。

type AddFileToDatasetRequest

type AddFileToDatasetRequest struct {
	DatasetID      int64  `json:"dataset_id,string" binding:"required"`
	ProjectID      int64  `json:"-"`
	AnalysisNodeID int64  `json:"analysis_node_id,string,omitempty"` // optional, if provided, the file will be linked to the analysis node
	Path           string `json:"path" binding:"required"`
	Role           string `json:"role"`
	FileName       string `json:"file_name" gorm:"type:varchar(255)"`
	IsCopy         bool   `json:"is_copy"`   // if true, copy the file to the dataset, otherwise just link it
	IsPrefix       bool   `json:"is_prefix"` // if true, the path is a prefix, and all files under the prefix will be added to the dataset
	// data analysis external
	Source string `json:"source"`
}

type AddFileToDatasetResponse

type AddFileToDatasetResponse struct {
	File        *File        `json:"file"`
	DatasetFile *DatasetFile `json:"dataset_file"`
}

type AgentProfileInfo added in v0.1.5

type AgentProfileInfo struct {
	ID          string `json:"id"`
	Name        string `json:"name"`
	Description string `json:"description,omitempty"`
	Model       string `json:"model,omitempty"`
	Provider    string `json:"provider,omitempty"`
	IsDefault   bool   `json:"is_default"`
	IsBuiltin   bool   `json:"is_builtin"`
}

AgentProfileInfo 是随用户信息返回的 Agent Profile 摘要(DTO)。

只暴露前端展示 / 选择所需的字段;Profile 的完整内容(系统提示词、技能等) 仍通过 /agent/profile 接口按 ID 获取。

type Analysis

type Analysis struct {
	// ID uint `json:"id" gorm:"primaryKey;autoIncrement"`
	ID int64 `json:"id,string" gorm:"primaryKey;type:bigint;autoIncrement:false"`
	// ProjectID   string `json:"project" gorm:"column:project;type:varchar(255)"`
	ProjectID   int64  `json:"project_id,string" gorm:"column:project_id;type:bigint"`
	AnalysisID  string `json:"analysis_id" gorm:"column:analysis_id;type:varchar(255)"`
	ComponentID string `json:"component_id" gorm:"column:component_id;type:varchar(255)"`
	// WorkflowID 是工作流主键(pipeline_components_relation.id),不再是 relation_id UUID。
	// 列名 workflow_id(历史列名为 relation_id,迁移见 migrations/2026-09-21-analysis-workflow-id)。
	WorkflowID int64 `json:"workflow_id,string" gorm:"column:workflow_id;type:bigint;index:idx_nextflow_workflow_id"`
	// AnalysisType        string    `json:"analysis_type" gorm:"column:analysis_type;type:varchar(255)"`
	AnalysisName   string `json:"analysis_name" gorm:"column:analysis_name;type:varchar(255)"`
	InputFile      string `json:"input_file" gorm:"column:input_file;type:varchar(255)"`
	AnalysisMethod string `json:"analysis_method" gorm:"column:analysis_method;type:varchar(255)"`
	// WorkspaceDir 是本次分析的根目录。落库时相对 storage.base_dir 存储,
	// 读取时由 repository 还原成绝对路径,因此 base_dir 变更只需拷贝目录,
	// 无需回写数据库。其余路径全部由它派生(见下方 gorm:"-" 字段)。
	WorkspaceDir        string `json:"workspace_dir" gorm:"column:workspace_dir;type:varchar(255)"`
	RequestParam        string `json:"request_param" gorm:"column:request_param;type:longtext"`
	OutputFormat        string `json:"output_format" gorm:"column:output_format;type:longtext"`
	PipelineScript      string `json:"pipeline_script" gorm:"column:pipeline_script;type:varchar(255)"`
	ParseAnalysisModule string `json:"parse_analysis_module" gorm:"column:parse_analysis_module;type:varchar(255)"`
	ProcessID           string `json:"process_id" gorm:"column:process_id;type:varchar(255)"`
	ScriptConfigFile    string `json:"script_config_file" gorm:"column:script_config_file;type:varchar(255)"`
	JobID               string `json:"job_id" gorm:"column:job_id;type:varchar(255)"`
	Ports               string `json:"ports" gorm:"column:ports;type:varchar(255)"`
	URL                 string `json:"url" gorm:"column:url;type:varchar(255)"`
	JobStatus           string `json:"job_status" gorm:"column:job_status;type:varchar(255)"`
	// ServerStatus        string `json:"server_status" gorm:"column:server_status;type:varchar(255)"`
	// SchedulerMode 记录推进本次分析的调度器,用于进程重启后把分析交回正确的调度器恢复。
	// 历史数据该列为空,按 legacy DAG 调度器处理(见 NormalizeSchedulerMode)。
	SchedulerMode    string    `json:"scheduler_mode" gorm:"column:scheduler_mode;type:varchar(64);default:''"`
	IsReport         bool      `json:"is_report" gorm:"column:is_report;default:false"`
	CacheType        int       `json:"cache_type" gorm:"column:cache_type;default:1"`
	Used             bool      `json:"used" gorm:"column:used;default:true"`
	DataComponentIDs string    `json:"data_component_ids" gorm:"column:data_component_ids;type:text"`
	ExtraProjectIDs  string    `json:"extra_project_ids" gorm:"column:extra_project_ids;type:longtext"`
	CreatedAt        time.Time `json:"created_at" gorm:"column:created_at"`
	UpdatedAt        time.Time `json:"updated_at" gorm:"column:updated_at"`

	// 以下是 WorkspaceDir 的派生路径,一律不落库(gorm:"-")。
	// repository 在读取时通过 HydrateDerivedPaths 填充,保证磁盘布局只有一处定义。
	ParamsPath      string `json:"params_path" gorm:"-"`
	CommandPath     string `json:"command_path" gorm:"-"`
	CommandLogPath  string `json:"command_log_path" gorm:"-"`
	TraceFile       string `json:"trace_file" gorm:"-"`
	WorkflowLogFile string `json:"workflow_log_file" gorm:"-"`
	ExecutorLogFile string `json:"executor_log_file" gorm:"-"`
}

Analysis maps to Python brave's nextflow table.

func (*Analysis) BeforeCreate

func (t *Analysis) BeforeCreate(_ *gorm.DB) error

func (*Analysis) HydrateDerivedPaths added in v0.1.4

func (t *Analysis) HydrateDerivedPaths()

HydrateDerivedPaths 从 WorkspaceDir 推导出全部派生路径。 WorkspaceDir 为空时派生路径全部为空,避免产生悬空的文件名。

func (Analysis) TableName

func (Analysis) TableName() string

type AnalysisControllerSaveInput

type AnalysisControllerSaveInput struct {
	RequestParam        map[string]any
	ParseAnalysisResult map[string]any
	DagRuntime          map[string]any
	Project             *Project
	IsRunNode           bool
	IsReport            bool
	// SchedulerMode 由各控制入口显式声明,标识谁来推进这次分析。
	// 为空时保持库中原值不变(更新路径)或按 legacy 处理(新建路径)。
	SchedulerMode string
}

type AnalysisEdge

type AnalysisEdge struct {
	ID             uint   `json:"id" gorm:"primaryKey;autoIncrement"`
	AnalysisEdgeID string `json:"analysis_edge_id" gorm:"column:analysis_edge_id;type:varchar(255)"`
	// AnalysisID     string `json:"analysis_id" gorm:"column:analysis_id;type:varchar(255);index:idx_analysis_edges_analysis_id"`
	AnalysisID int64 `json:"analysis_id,string" gorm:"column:analysis_id;type:bigint"`

	SourceNode   string    `json:"source_node" gorm:"column:source_node;type:varchar(255)"`
	TargetNode   string    `json:"target_node" gorm:"column:target_node;type:varchar(255)"`
	SourceHandle string    `json:"source_handle" gorm:"column:source_handle;type:varchar(255)"`
	TargetHandle string    `json:"target_handle" gorm:"column:target_handle;type:varchar(255)"`
	CreatedAt    time.Time `json:"created_at" gorm:"column:created_at"`
	UpdatedAt    time.Time `json:"updated_at" gorm:"column:updated_at"`
}

AnalysisEdge maps to Python brave's analysis_edges table.

func (AnalysisEdge) TableName

func (AnalysisEdge) TableName() string

type AnalysisNode

type AnalysisNode struct {
	// ID                     uint       `json:"id" gorm:"primaryKey;autoIncrement"`
	ID int64 `json:"id,string" gorm:"primaryKey;type:bigint;autoIncrement:false"`

	AnalysisNodeID string `json:"analysis_node_id" gorm:"column:analysis_node_id;type:varchar(255)"`
	// ProjectID      string `json:"project_id" gorm:"column:project_id;type:varchar(255);index:idx_analysis_nodes_project_id"`
	ProjectID int64 `json:"project_id,string" gorm:"column:project_id;type:bigint"`
	// AnalysisID string `json:"analysis_id" gorm:"column:analysis_id;type:varchar(255);index:idx_analysis_nodes_analysis_id;index:idx_analysis_nodes_analysis_id_status,priority:1;index:idx_analysis_nodes_analysis_id_node_id,priority:1"`
	AnalysisID int64  `json:"analysis_id,string" gorm:"column:analysis_id;type:bigint"`
	NodeID     string `json:"node_id" gorm:"column:node_id;type:varchar(255);index:idx_analysis_nodes_analysis_id_node_id,priority:2"`
	NodeName   string `json:"node_name" gorm:"column:node_name;type:varchar(255)"`
	SampleID   string `json:"sample_id" gorm:"column:sample_id;type:varchar(255)"`
	// ScriptID       string `json:"script_id" gorm:"column:script_id;type:varchar(255)"`
	ScriptID int64 `json:"script_id,string" gorm:"column:script_id;type:bigint"`
	// ContainerTemplateID 是节点级容器模板(go_container_template_definition 主键)。
	//
	// 由 Agent 创建的「命令节点」没有脚本,直接用它启动容器;由脚本创建的节点保持 0,
	// 沿用脚本绑定的 container_template_id(见 dag/executor.ContainerExecutor)。
	ContainerTemplateID int64 `json:"container_template_id,string" gorm:"column:container_template_id;type:bigint"`
	// ScriptName 不是 analysis_nodes 的列,而是按 ScriptID join pipeline_components
	// 取到的脚本名称(component_name 列)。只有显式 join 的查询才会填充,
	// 因此用 gorm:"-" 排除在 schema 之外,避免其他查询误选该列。
	ScriptName             string    `json:"script_name" gorm:"-"`
	InputsPatterns         JSONMap   `json:"inputs_patterns" gorm:"column:inputs_patterns;type:json"`
	ResolvedInputs         JSONMap   `json:"resolved_inputs" gorm:"column:resolved_inputs;type:json"`
	OutputPatterns         JSONMap   `json:"output_patterns" gorm:"column:output_patterns;type:json"`
	ResolvedOutputs        JSONMap   `json:"resolved_outputs" gorm:"column:resolved_outputs;type:json"`
	OutputFileIDs          JSONMap   `json:"output_file_ids" gorm:"column:output_file_ids;type:json"` // 输出句柄 -> go_file id,供下游 SelectAssay 输入还原为 {"files": "<id>"}
	RequestParam           string    `json:"request_param" gorm:"column:request_param;type:longtext"`
	CPU                    int       `json:"cpu" gorm:"column:cpu"`
	Memory                 string    `json:"memory" gorm:"column:memory;type:varchar(64)"`
	Disk                   string    `json:"disk" gorm:"column:disk;type:varchar(64)"`
	GPU                    int       `json:"gpu" gorm:"column:gpu"`
	Status                 string    `json:"status" gorm:"column:status;type:varchar(64);index:idx_analysis_nodes_analysis_id_status,priority:2"`
	ServerStatus           string    `json:"server_status" gorm:"column:server_status;type:varchar(64)"`
	PID                    int       `json:"pid" gorm:"column:pid"`
	JobID                  string    `json:"job_id" gorm:"column:job_id;type:varchar(255)"`
	Executor               string    `json:"executor" gorm:"column:executor;type:varchar(64)"`
	Retry                  int       `json:"retry" gorm:"column:retry;default:0"`
	MaxRetry               int       `json:"max_retry" gorm:"column:max_retry;default:3"`
	ExitCode               int       `json:"exit_code" gorm:"column:exit_code"`
	ErrorMessage           string    `json:"error_message" gorm:"column:error_message;type:text"`
	RerunReason            string    `json:"rerun_reason" gorm:"column:rerun_reason;type:text"`
	InputHash              string    `json:"input_hash" gorm:"column:input_hash;type:varchar(255)"`
	CacheHit               bool      `json:"cache_hit" gorm:"column:cache_hit"`
	UpstreamIDs            JSONSlice `json:"upstream_ids" gorm:"column:upstream_ids;type:json"`
	DownstreamIDs          JSONSlice `json:"downstream_ids" gorm:"column:downstream_ids;type:json"`
	InputValidationErrors  JSONSlice `json:"input_validation_errors" gorm:"column:input_validation_errors;type:json"`
	OutputValidationErrors JSONSlice `json:"output_validation_errors" gorm:"column:output_validation_errors;type:json"`
	// WorkspaceDir 是节点根目录。落库时相对 storage.base_dir 存储,
	// 读取时由 repository 还原成绝对路径。其余路径全部由它派生。
	WorkspaceDir   string     `json:"workspace_dir" gorm:"column:workspace_dir;type:varchar(255)"`
	CommandMD5     string     `json:"command_md5" gorm:"column:command_md5;type:varchar(64)"`
	ParamsMD5      string     `json:"params_md5" gorm:"column:params_md5;type:varchar(64)"`
	CreationSource string     `json:"creation_source" gorm:"column:creation_source;type:varchar(32)"`
	StartedAt      *time.Time `json:"started_at" gorm:"column:started_at"`
	FinishedAt     *time.Time `json:"finished_at" gorm:"column:finished_at"`
	CreatedAt      time.Time  `json:"created_at" gorm:"column:created_at"`
	UpdatedAt      time.Time  `json:"updated_at" gorm:"column:updated_at"`

	// 以下是 WorkspaceDir 的派生路径,一律不落库(gorm:"-")。
	// repository 在读取时通过 HydrateDerivedPaths 填充。
	LogPath     string `json:"log_path" gorm:"-"`
	OutputDir   string `json:"output_dir" gorm:"-"`
	CacheDir    string `json:"cache_dir" gorm:"-"`
	CommandPath string `json:"command_path" gorm:"-"`
	ParamsPath  string `json:"params_path" gorm:"-"`
}

AnalysisNode maps to Python brave's analysis_nodes table.

func (*AnalysisNode) BeforeCreate

func (t *AnalysisNode) BeforeCreate(_ *gorm.DB) error

func (*AnalysisNode) HydrateDerivedPaths added in v0.1.4

func (t *AnalysisNode) HydrateDerivedPaths()

HydrateDerivedPaths 从 WorkspaceDir 推导出全部派生路径。 WorkspaceDir 为空时派生路径全部为空,避免产生悬空的文件名。

func (*AnalysisNode) IsCommandNode added in v0.2.0

func (t *AnalysisNode) IsCommandNode() bool

IsCommandNode 报告该节点是否为 Agent 创建的命令节点。

命令节点没有脚本:它的容器模板由节点自身承载(ContainerTemplateID),run.sh 由 创建 / 更新入口直接写盘(见 prepare.WriteCommandRunScript),因此运行期跳过脚本 相关的解析与软链。

func (*AnalysisNode) NodeType added in v0.2.0

func (t *AnalysisNode) NodeType() string

NodeType 返回节点的归一化类型:agent / script / scheduler。

优先读取 creation_source(三种规范值);同时兼容历史取值:

  • standalone(前端独立节点)视为 script;
  • agent_session(Agent 命令节点)视为 agent;
  • 旧 create_script_analysis 曾把脚本节点标记为 agent,这里按「绑定脚本」纠正为 script。

creation_source 为空或未知时按节点形状推断;仍无法判定时返回空串。

func (*AnalysisNode) NodeTypeDescription added in v0.2.0

func (t *AnalysisNode) NodeTypeDescription() string

NodeTypeDescription 返回节点类型的中文说明,便于工具结果直接回给模型。

func (AnalysisNode) TableName

func (AnalysisNode) TableName() string

type AnalysisQuery

type AnalysisQuery = AnalysisQuey

AnalysisQuery is an alias of AnalysisQuey for clearer naming in new code.

type AnalysisQuey

type AnalysisQuey struct {
	IDs []int64 `json:"ids,omitempty"`

	ID *int64 `json:"id,string,omitempty"`

	ProjectID int64 `json:"project_id,string,omitempty"`

	AnalysisID string `json:"analysis_id,omitempty"`

	AnalysisName string `json:"analysis_name,omitempty"`

	// WorkflowID 过滤条件,取值是工作流主键(pipeline_components_relation.id)。
	WorkflowID int64 `json:"workflow_id,string,omitempty"`

	JobStatus string `json:"job_status,omitempty"`

	ServerStatus string `json:"server_status,omitempty"`

	IsReport *bool `json:"is_report,omitempty"`

	CacheType *int `json:"cache_type,omitempty"`

	SortBy string `json:"sort_by,omitempty"`

	SortOrder string `json:"sort_order,omitempty"`
}

AnalysisQuey defines optional filters and sorting for analysis pagination. Keep the type name for compatibility with existing callers.

func (*AnalysisQuey) GetAnalysisID

func (q *AnalysisQuey) GetAnalysisID() string

func (*AnalysisQuey) GetAnalysisName

func (q *AnalysisQuey) GetAnalysisName() string

func (*AnalysisQuey) GetJobStatus

func (q *AnalysisQuey) GetJobStatus() string

func (*AnalysisQuey) GetServerStatus

func (q *AnalysisQuey) GetServerStatus() string

func (*AnalysisQuey) GetSortColumn

func (q *AnalysisQuey) GetSortColumn() string

func (*AnalysisQuey) GetSortOrder

func (q *AnalysisQuey) GetSortOrder() string

func (*AnalysisQuey) GetWorkflowID

func (q *AnalysisQuey) GetWorkflowID() int64

type AppSession

type AppSession struct {
	ID int64 `json:"id,string" gorm:"primaryKey;type:bigint;autoIncrement:false"`

	UserID    int64 `json:"user_id,string" gorm:"type:bigint;index;not null"`
	ProjectID int64 `json:"project_id,string" gorm:"column:project_id;type:bigint"`

	AnalysisNodeID int64 `json:"analysis_node_id,string" gorm:"index"`

	ContainerTemplateID int64 `json:"container_template_id,string" gorm:"index;not null"`

	Name string `json:"name" gorm:"type:varchar(255);not null"`

	Status string `json:"status" gorm:"type:varchar(32);index;not null;default:PENDING"`

	WorkspacePath string `json:"workspace_path" gorm:"type:varchar(1024)"`

	// AgentSessionID 记录创建该会话的 Agent 会话 ID(agent_sessions.id)。
	//
	// 0 表示用户从 UI 手动创建;>0 表示由 Agent 的 terminal_exec / 容器 coder bash 创建,
	// 同一 (container_template_id, agent_session_id) 唯一,保证同一 Agent 会话在同一模板上
	// 只复用一个终端会话(同一个容器与 PTY)。
	AgentSessionID int64 `json:"agent_session_id,string" gorm:"index;not null;default:0"`

	// Persistent 标记会话是否为「持久会话」。
	//
	// true  = 只能由空闲 TTL 到期或用户显式关闭(DELETE /container/terminal/session/{id})回收;
	// false = 一次性会话:最后一个订阅者(terminal_exec / WS)离开后立即回收容器与会话。
	//
	// 用户从 UI 创建的会话一律持久;Agent 创建的一次性会话经前端打开后也会被置为 true,
	// 并且此后不会再退回 false(只增不减)。
	Persistent bool `json:"persistent" gorm:"not null;default:false"`

	// SessionKind 标记会话的「种类」,取值见 AppSessionKind*:
	//   - web      :ContainerService.CreateAppSessionByTemplate(容器跑模板命令,前端经网关访问应用);
	//   - terminal :终端会话注册表 createOrAdopt(容器常驻,交互式 shell 由运行时 exec 打开)。
	//
	// 它描述会话本身,而不是「谁创建的」:创建者见 AgentSessionID,生命周期策略见 Persistent。
	// 历史行在加列之前就已存在,回填见 migrations/2026-11-06-app-session-kind;
	// 仍为空时读取方用 NormalizedSessionKind 兜底。
	SessionKind string `json:"session_kind" gorm:"column:session_kind;type:varchar(32);index;not null;default:web"`

	LastAccessAt *time.Time `json:"last_access_at"`

	StartedAt *time.Time `json:"started_at"`

	StoppedAt *time.Time `json:"stopped_at"`

	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`
}

AppSession 的状态机 PENDING

↓

CREATING

↓

RUNNING

↓

STOPPED

↓

RESUMING

↓

FAILED

func (*AppSession) BeforeCreate

func (t *AppSession) BeforeCreate(_ *gorm.DB) error

func (*AppSession) NormalizedSessionKind added in v0.2.0

func (a *AppSession) NormalizedSessionKind() string

NormalizedSessionKind 返回归一化后的会话种类。

加列之前的历史行只有迁移回填的值;仍为空时按 AgentSessionID / Persistent 推断 (终端会话至少满足其一),其余一律视为 Web 应用会话,避免前端展示空标签。

func (AppSession) TableName

func (AppSession) TableName() string

type AppSessionEvent added in v0.2.0

type AppSessionEvent struct {
	// AppSessionID 是会话主键(= types.AppSession.ID)。
	AppSessionID int64
	// UserID 是接收推送的用户;0 表示无接收者,handler 直接丢弃。
	UserID    int64
	ProjectID int64
	// ContainerTemplateID 是会话使用的容器模板(终端标签按模板分组时使用)。
	ContainerTemplateID int64
	// Status 是会话最新状态(RUNNING / STOPPED / ...),为空时沿用数据库里的值。
	Status string
	// Method 是前端 component.invoke 的 method:sessionCreated / sessionDeleted /
	// sessionRunning / sessionIdle / sessionAttached / sessionDetached。
	Method string
	// Action 为空表示 component.invoke;其它值(如 terminal.exec)作为 action 直接推送。
	Action string
	// Args 是随事件一起推给前端的参数(busy / subscribers / persistent / command ...)。
	Args map[string]any
}

AppSessionEvent 是「会话层 → 实时层」的统一事件。

会话层(manager.TerminalSessionRegistry)不再自己推 WebSocket 消息,而是把会话 生命周期 / 运行态变化发布到 event.Bus,由 manager.AppSessionEventHandler 统一 转成前端消息,保证「会话状态推送」只有一个出口:

  • Action 为空 → action=component.invoke,category=app-session, id=会话 ID,method=Method,args=Args(前端列表据此 refetch);
  • Action=terminal.exec → 直接以 Args 作为 payload 推送,前端据此自动打开终端标签。

type AppSessionPageQuery

type AppSessionPageQuery struct {
	AnalysisNodeID *int64 `json:"analysis_node_id,string,omitempty"`
	ProjectID      *int64 `json:"project_id,omitempty"`
}

type ArticleCursor

type ArticleCursor struct {
	SortBy string `json:"sort_by"`
	// Value stores the current sort field's value as string.
	Value string `json:"value"`
	// ID is the tiebreaker for stable ordering.
	ID int64 `json:"id"`
}

ArticleCursor is the cursor payload for article pagination. It uses sort_by + value + id to build a stable ordering cursor.

func DecodeArticleCursor

func DecodeArticleCursor(cursor string) (ArticleCursor, error)

DecodeArticleCursor decodes an opaque cursor string.

type Assay added in v0.1.5

type Assay struct {
	ID int64 `json:"id,string" gorm:"primaryKey;type:bigint;autoIncrement:false"`

	// SampleName 是样本的业务编号兼展示名(列 go_assay.sample_name),例如
	// S-001 / 脾脏-6。无需全局唯一,只在同一个 dataset 下唯一(经
	// go_dataset_assay 绑定判定);同一个名字可以出现在不同 dataset。
	SampleName string `json:"sample_name" gorm:"type:varchar(255);index;not null"`

	AssayType string `json:"assay_type" gorm:"type:varchar(64);index"`

	Platform string `json:"platform" gorm:"type:varchar(128)"`

	LibraryID string `json:"library_id" gorm:"type:varchar(255)"`

	// Role 是该 assay 的角色(列 go_assay.role),例如 DEFAULT / TABLE;
	// input_type=assay 的表单输入用 resolver.accept_formats 与之匹配(与
	// go_file.role 对文件的口径一致)。空表示不参与角色过滤。
	Role string `json:"role" gorm:"type:varchar(64);index"`

	Metadata string `json:"metadata" gorm:"type:text"`

	Description string `json:"description" gorm:"type:text"`

	CreatedAt time.Time `json:"created_at"`

	UpdatedAt time.Time `json:"updated_at"`
}

Assay 是一次实验/测序建库记录,直接隶属于某个 Dataset(Dataset -> DatasetAssay -> Assay -> File)。其下文件(go_file.assay_id)是 assay 私有的,不跨 assay 复用。

func (*Assay) BeforeCreate added in v0.1.5

func (t *Assay) BeforeCreate(_ *gorm.DB) error

func (Assay) TableName added in v0.1.5

func (Assay) TableName() string

type AssayWithDatasetInfo added in v0.1.5

type AssayWithDatasetInfo struct {
	ID int64 `json:"id,string"`

	SampleName string `json:"sample_name"`

	AssayType string `json:"assay_type"`

	Platform string `json:"platform"`

	LibraryID string `json:"library_id"`

	// Role 是该 assay 的角色(go_assay.role),例如 DEFAULT / TABLE;
	// input_type=assay 的表单输入用 resolver.accept_formats 与之匹配,
	// resolveFormAnalysisResult 据此把 assay 分组挂到 analysis_result[role]。
	Role string `json:"role"`

	Metadata string `json:"metadata"`

	Description string `json:"description"`

	CreatedAt time.Time `json:"created_at"`

	UpdatedAt time.Time `json:"updated_at"`

	DatasetID string `json:"dataset_id"`

	DatasetName string `json:"dataset_name"`
}

AssayWithDatasetInfo is the read model of an Assay joined with the dataset it is bound to through go_dataset_assay, used by the project-wide assay queries. The assay itself carries its SampleName, so no sample join is needed.

type AuthToken

type AuthToken struct {
	// Unique identifier of the token
	ID int64 `json:"id,string" gorm:"primaryKey;type:bigint;autoIncrement:false"`
	// User ID that owns this token
	UserID int64 `json:"user_id,string" gorm:"type:bigint;index;not null"`
	// Token value (JWT or other format)
	Token string `json:"token"      gorm:"type:text;not null"`
	// Token type (access_token, refresh_token)
	TokenType string `json:"token_type" gorm:"type:varchar(50);not null"`
	// Token expiration time
	ExpiresAt time.Time `json:"expires_at"`
	// Whether the token is revoked
	IsRevoked bool `json:"is_revoked" gorm:"default:false"`
	// Creation time of the token
	CreatedAt time.Time `json:"created_at"`
	// Last updated time of the token
	UpdatedAt time.Time `json:"updated_at"`

	// Association relationship
	User *User `json:"user,omitempty" gorm:"foreignKey:UserID"`
}

AuthToken represents an authentication token

func (*AuthToken) BeforeCreate added in v0.2.0

func (t *AuthToken) BeforeCreate(_ *gorm.DB) error

BeforeCreate assigns a snowflake ID when the token is created without one.

type ContainerEvent

type ContainerEvent struct {
	ID int64 `json:"id,string" gorm:"primaryKey;type:bigint;autoIncrement:false"`

	ContainerInstanceID int64 `json:"container_instance_id,string" gorm:"index;not null"`

	Event string `json:"event" gorm:"type:varchar(64);index;not null"`

	Message string `json:"message" gorm:"type:text"`

	CreatedAt time.Time `json:"created_at"`
}

func (*ContainerEvent) BeforeCreate

func (t *ContainerEvent) BeforeCreate(_ *gorm.DB) error

func (ContainerEvent) TableName

func (ContainerEvent) TableName() string

type ContainerInstance

type ContainerInstance struct {
	ID int64 `json:"id,string" gorm:"primaryKey;type:bigint;autoIncrement:false"`

	TemplateID int64 `json:"template_id,string" gorm:"index;not null"`

	OwnerType ContainerOwnerType `json:"owner_type" gorm:"type:varchar(30);index;not null"`

	OwnerID int64 `json:"owner_id,string" gorm:"index;not null"`

	// Kind 是容器的运行形态(取值见 ContainerInstanceKind*),决定创建时如何组装运行时
	// spec。它独立于 OwnerType:终端会话容器的 owner 也是 app_session。
	// 历史数据该列为空,读取方用 NormalizedKind 兜底(按 OwnerType 推断)。
	Kind ContainerInstanceKind `json:"kind" gorm:"column:kind;type:varchar(32);index;not null;default:web"`

	RuntimeName string `json:"runtime_name" gorm:"type:varchar(255);index;not null"`

	RuntimeID string `json:"runtime_id" gorm:"type:varchar(255);index"`

	Name string `json:"name" gorm:"type:varchar(255);not null;index"`

	Status ContainerStatus `json:"status" gorm:"type:varchar(30);index;not null;default:pending"`

	IPAddress       string `json:"ip_address" gorm:"type:varchar(128)"`
	RuntimeNodeName string `json:"runtime_node_name" gorm:"type:varchar(255);index"`

	// HostPort 是容器端口发布到宿主机后的实际端口(0 表示未发布)。
	// 只有 container.network_mode=host_port 时非 0;由运行时 Inspect 读回,
	// 供路由层用「宿主机 + HostPort」代替「容器 IP + 容器端口」。
	HostPort int `json:"host_port" gorm:"not null;default:0"`

	ExitCode *int `json:"exit_code"`

	StartedAt *time.Time `json:"started_at"`

	FinishedAt *time.Time `json:"finished_at"`

	CreatedAt time.Time `json:"created_at"`

	UpdatedAt time.Time `json:"updated_at"`
}

func (*ContainerInstance) BeforeCreate

func (t *ContainerInstance) BeforeCreate(_ *gorm.DB) error

func (*ContainerInstance) NormalizedKind added in v0.2.0

func (t *ContainerInstance) NormalizedKind() ContainerInstanceKind

NormalizedKind 返回实例的运行形态:Kind 已显式设置时直接返回,否则按 OwnerType 推断(历史数据的兜底),最终默认 web。

func (ContainerInstance) TableName

func (ContainerInstance) TableName() string

type ContainerInstanceKind added in v0.2.0

type ContainerInstanceKind string

ContainerInstanceKind 标识容器的「运行形态」:它决定 executeCreateInstance 如何组装 运行时 spec(启动命令、workload 类型、是否以宿主用户运行、是否暴露服务等)。

它与 ContainerOwnerType 是两个维度:OwnerType 说明「容器属于谁 / 用于回收」, Kind 说明「容器怎么跑」。例如终端会话容器的 owner 也是 app_session, 但 Kind 必须是 ContainerInstanceKindTerminal。

const (
	// ContainerInstanceKindWeb 是 Web 应用容器:跑模板命令、暴露服务,
	// 由网关按 AppSession 转发流量(OwnerType=app_session)。
	ContainerInstanceKindWeb ContainerInstanceKind = "web"
	// ContainerInstanceKindTerminal 是终端会话容器:常驻 keep-alive 进程,
	// 真正的交互式 shell 由 docker exec / kubectl exec 打开(Sync=true 创建)。
	ContainerInstanceKindTerminal ContainerInstanceKind = "terminal"
	// ContainerInstanceKindDagNode 是 DAG 节点任务容器:统一入口 bash ./run.sh,
	// 跑完即退出(OwnerType=dag_node)。
	ContainerInstanceKindDagNode ContainerInstanceKind = "dag_node"
)

func NormalizeContainerInstanceKind added in v0.2.0

func NormalizeContainerInstanceKind(raw string) ContainerInstanceKind

NormalizeContainerInstanceKind 校验并归一化容器运行形态;空值或未知取值返回 ""。

type ContainerOwnerType

type ContainerOwnerType string
const (
	ContainerOwnerDagNode    ContainerOwnerType = "dag_node"
	ContainerOwnerAppSession ContainerOwnerType = "app_session"
	ContainerOwnerService    ContainerOwnerType = "service"
	// ContainerOwnerTerminal 标识「容器模板终端会话」容器:只服务于交互式 PTY,
	// 不参与 DAG / AppSession 的容器生命周期编排。
	ContainerOwnerTerminal ContainerOwnerType = "terminal"
)

type ContainerSchedulingConstraint

type ContainerSchedulingConstraint struct {
	Type     string   `json:"type"`
	Key      string   `json:"key"`
	Operator string   `json:"operator"`
	Values   []string `json:"values,omitempty"`
}

type ContainerSchedulingSelector

type ContainerSchedulingSelector struct {
	Constraints []ContainerSchedulingConstraint `json:"constraints"`
}

type ContainerSpec

type ContainerSpec struct {
	Image                string
	Entrypoint           []string
	Command              []string
	Env                  map[string]string
	Volumes              []ContainerVolume
	SupplementalGroups   []int64
	SchedulingConstraint *ContainerSchedulingSelector
	User                 string
	Labels               map[string]string

	// HomeDir 非空时作为容器的 HOME(容器内绝对路径),由 runtime 落到环境变量
	// HOME 上(docker: -e HOME=...,k8s: env HOME=...)。
	//
	// 以非 root 用户运行时(User 非空)镜像里的 HOME 往往不可写(例如 /root),
	// 需要同时配合 Tmpfs 把 HOME 挂成可写的内存盘。
	HomeDir string
	// Tmpfs 是以内存盘(tmpfs)挂载的容器内路径,落地方式由 runtime 决定:
	// docker 映射 HostConfig.Tmpfs,kubernetes 映射 EmptyDir{Medium: Memory}。
	//
	// 典型用法是给非 root 用户挂一个可写的 HOME:
	//
	//	docker run --user "$UID:$GID" -e HOME=/home/app \
	//	  --tmpfs /home/app:rw,uid=$UID,gid=$GID,mode=700
	Tmpfs []ContainerTmpfs

	// PullPolicy 来自容器模板绑定行(ContainerTemplateDefinition.PullPolicy),
	// 取值 Always / IfNotPresent / Never,空值按 IfNotPresent 处理。落地方式由 runtime 决定:
	// docker 没有 imagePullPolicy 概念,在 create 前按策略决定是否 pull;
	// kubernetes 直接映射为 container.imagePullPolicy。
	PullPolicy string

	CPU    float64
	Memory int64

	WorkDir          string
	RuntimeName      string
	RuntimeNamespace string
	WorkloadKind     string
	ExposedPort      int
	ExposeService    bool

	// PublishPort 为 true 时把 ExposedPort 以随机宿主机端口发布(-p 0.0.0.0:0:<port>),
	// 供 gobrave 之外的进程(如 Windows 宿主浏览器)访问。
	//
	// docker 与 k8s 语义不同:docker 由 docker runtime 落地为 PortBindings;
	// k8s 的 ExposeService 已经通过 Service/Ingress 暴露,不读取本字段。
	PublishPort bool
}

type ContainerStatus

type ContainerStatus string
const (
	ContainerCreatePending   ContainerStatus = "create_pending"
	ContainerReCreatePending ContainerStatus = "recreate_pending"
	ContainerReCreating      ContainerStatus = "recreating"
	ContainerCreating        ContainerStatus = "creating"
	ContainerRunning         ContainerStatus = "running"
	ContainerPaused          ContainerStatus = "paused"
	ContainerStopPending     ContainerStatus = "stop_pending"
	ContainerStopping        ContainerStatus = "stopping"
	ContainerStartPending    ContainerStatus = "start_pending"
	ContainerStarting        ContainerStatus = "starting"
	ContainerStopped         ContainerStatus = "stopped"
	ContainerDeleted         ContainerStatus = "deleted"
	ContainerFailed          ContainerStatus = "failed"
	ContainerExited          ContainerStatus = "exited"
	ContainerDeletePending   ContainerStatus = "delete_pending"
	ContainerDeleting        ContainerStatus = "deleting"
)

type ContainerTemplate

type ContainerTemplate struct {
	ID     int64 `json:"id,string"`
	SpecID int64 `json:"spec_id,string"`

	Name        string `json:"name"`
	Description string `json:"description"`
	// ImageName / PullPolicy 原样取自绑定行 ContainerTemplateDefinition。
	ImageName  string `json:"image_name"`
	PullPolicy string `json:"pull_policy"`
	// DisplayName 原样取自绑定行 ContainerTemplateDefinition.DisplayName(不做回退)。
	// Name 才是对外展示名:DisplayName 非空时覆盖共享配置名,否则回退到 spec.Name。
	// 编辑表单必须读写 DisplayName,否则会把回退出来的配置名误固化成绑定行展示名。
	DisplayName string `json:"display_name"`
	// DefinitionDescription 原样取自绑定行 ContainerTemplateDefinition.Description(长文本)。
	// 与 Description(共享运行配置 spec 的描述)相互独立,编辑表单需读写本字段。
	DefinitionDescription string `json:"definition_description"`
	// IsDefault 原样取自绑定行 ContainerTemplateDefinition.IsDefault。
	IsDefault bool `json:"is_default"`

	Command string  `json:"command"`
	CPU     float64 `json:"cpu"`
	Memory  int64   `json:"memory"`

	Port    int    `json:"port"`
	AppType string `json:"app_type"`

	Env                  datatypes.JSON `json:"env"`
	Mounts               datatypes.JSON `json:"mounts"`
	SchedulingConstraint datatypes.JSON `json:"scheduling_constraint"`
	Labels               datatypes.JSON `json:"labels"`
	ChangeUID            bool           `json:"change_uid"`

	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`
}

ContainerTemplate 不是持久化对象,由 repo 层读取 go_container_template_definition + go_container_template_spec 组装返回。 ID == ContainerTemplateDefinition.ID:引用方(script.container_template_id / app_session.container_template_id / container_instance.template_id)语义不变, 同时天然锁定了该模板要使用的镜像。

与 ContainerTemplateSpec 一样,这里没有 WorkDir:容器工作目录在创建时统一取 运行时变量 PROJECT_DIR。

func NewContainerTemplate added in v0.1.4

func NewContainerTemplate(spec *ContainerTemplateSpec, binding *ContainerTemplateDefinition) *ContainerTemplate

NewContainerTemplate 把共享配置与绑定行组装成对外读模型。spec 允许为 nil(只取绑定行字段)。 binding 为 nil 时返回 nil。

func (*ContainerTemplate) ToExport added in v0.1.4

ToExport 把对外读模型(ContainerTemplate = definition + spec)还原成统一平铺格式。 spec 为 nil 时用读模型自身的字段重建(缺完整元数据时按主键再去库里取即可)。

func (*ContainerTemplate) ToTemplateSpec added in v0.2.0

func (t *ContainerTemplate) ToTemplateSpec() *ContainerTemplateSpec

ToTemplateSpec 把读模型里平铺的运行配置字段还原成 ContainerTemplateSpec(主键取 SpecID)。 读模型没有配置的元数据(created_at 等),需要完整配置时请按 SpecID 单独读取。

type ContainerTemplateBundle added in v0.2.0

type ContainerTemplateBundle struct {
	ContainerTemplateSpecs       []ContainerTemplateSpec       `json:"container_template_specs"`
	ContainerTemplateDefinitions []ContainerTemplateDefinition `json:"container_template_definitions"`
}

ContainerTemplateBundle 是容器模板的导出 / 导入格式,也是 script.json 与 workflow.json 里容器资产部分的结构本身 —— 三处的字段名与语义完全一致,统一在这一处定义:

container_template_specs       []ContainerTemplateSpec
container_template_definitions []ContainerTemplateDefinition

两者通过主键互相引用(definition.spec_id → spec.id),而 definition.id 就是脚本 container_template_id 引用的值;镜像名与拉取策略直接挂在绑定行上,因此:

  • 导出不写 created_at / updated_at(主键才是引用键,时间戳只会产生无意义的 git diff);
  • 导入按主键 upsert,顺序固定为「运行配置 → 绑定行」 (实现见 exportcodec.InstallContainerAssets,script / workflow 复用同一份逻辑)。

func NewContainerTemplateBundle added in v0.2.0

func NewContainerTemplateBundle() *ContainerTemplateBundle

NewContainerTemplateBundle 返回空 bundle(切片非 nil,序列化为 [] 而不是 null)。

type ContainerTemplateDefinition added in v0.1.4

type ContainerTemplateDefinition struct {
	ID int64 `json:"id,string" gorm:"primaryKey;type:bigint;autoIncrement:false"`

	SpecID int64 `json:"spec_id,string" gorm:"index;not null"`

	// ImageName 是完整镜像名(含 registry / namespace / tag),如 docker.io/rocker/rstudio:4.4。
	// 同一运行配置下不允许重复绑定同一镜像由服务层校验(不用唯一索引,便于旧数据迁移)。
	ImageName string `json:"image_name" gorm:"type:varchar(512);index"`

	// PullPolicy 是该绑定行的镜像拉取策略,取值 Always / IfNotPresent / Never,空值按 IfNotPresent 处理。
	// 落地方式由 runtime 决定:docker 在 create 前按策略决定是否 pull;kubernetes 直接映射为
	// container.imagePullPolicy。
	PullPolicy string `json:"pull_policy" gorm:"type:varchar(32);index;not null;default:IfNotPresent"`

	// DisplayName 为空时,对外名称回退到 ContainerTemplateConfig.Name。
	DisplayName string `json:"display_name" gorm:"type:varchar(255)"`

	// Description 是绑定行自身的描述(长文本),与共享运行配置 ContainerTemplateSpec.Description
	// 相互独立:spec 描述“怎么跑”,这里描述“这个可运行模板是做什么的 / 适用什么场景”。
	// Agent 工具 get_container_template 会把 DisplayName 与 Description 一起回传给模型。
	Description string `json:"description" gorm:"type:longtext"`

	// IsDefault 标记「默认容器模板」:只能有一行处于默认状态,由服务层在写入时互斥维护。
	// 创建脚本(create_script)未显式指定 container_template_id 时,优先取这一行。
	// 导出时会置为 false(omitempty 使其不出现在导出文件里)。
	IsDefault bool `json:"is_default,omitempty" gorm:"not null;default:false;index"`

	// 指针类型是为了让导出可以显式清空(omitempty 也因此生效);接口响应仍会带上时间字段。
	CreatedAt *time.Time `json:"created_at,omitempty"`
	UpdatedAt *time.Time `json:"updated_at,omitempty"`
}

ContainerTemplateDefinition 一行即"一个可直接运行的容器模板":共享配置 + 一个具体镜像。 镜像不再单独建表:完整镜像名与拉取策略直接放在绑定行上,因此一行就唯一确定了一个 可运行配置;同一 SpecID 可绑定多个不同镜像((SpecID, ImageName) 组合唯一)。 注意:该表主键 ID 就是对外暴露的 ContainerTemplate.ID。

func (*ContainerTemplateDefinition) BeforeCreate added in v0.1.4

func (t *ContainerTemplateDefinition) BeforeCreate(_ *gorm.DB) error

func (ContainerTemplateDefinition) TableName added in v0.1.4

func (ContainerTemplateDefinition) TableName() string

type ContainerTemplateSpec added in v0.1.4

type ContainerTemplateSpec struct {
	ID int64 `json:"id,string" gorm:"primaryKey;type:bigint;autoIncrement:false"`

	Name        string `json:"name" gorm:"type:varchar(255);not null;index"`
	Description string `json:"description" gorm:"type:text"`

	Command string `json:"command" gorm:"type:text"`

	CPU    float64 `json:"cpu"`
	Memory int64   `json:"memory"`

	Port    int    `json:"port" gorm:"not null;default:8787"`
	AppType string `json:"app_type" gorm:"type:varchar(32);index"`

	Env                  datatypes.JSON `json:"env" gorm:"type:json"`
	Mounts               datatypes.JSON `json:"mounts" gorm:"type:json"`
	SchedulingConstraint datatypes.JSON `json:"scheduling_constraint" gorm:"type:json"`
	Labels               datatypes.JSON `json:"labels" gorm:"type:json"`
	ChangeUID            bool           `json:"change_uid" gorm:"default:false"`

	// 指针类型是为了让导出可以显式清空(omitempty 也因此生效);接口响应仍会带上时间字段。
	CreatedAt *time.Time `json:"created_at,omitempty"`
	UpdatedAt *time.Time `json:"updated_at,omitempty"`
}

ContainerTemplateSpec 只描述"怎么跑":命令、资源、端口、环境变量、挂载、标签等, 不包含镜像。镜像由 ContainerTemplateDefinition 关联,因此同一套运行配置可被多个镜像复用。

这里刻意没有工作目录:容器的工作目录统一在创建时取运行时变量 PROJECT_DIR (DAG 节点任务型容器仍由 applyTaskRuntimeSpec 覆盖为节点工作区), 模板不再允许自定义 work_dir。

func (*ContainerTemplateSpec) BeforeCreate added in v0.1.4

func (t *ContainerTemplateSpec) BeforeCreate(_ *gorm.DB) error

func (ContainerTemplateSpec) TableName added in v0.1.4

func (ContainerTemplateSpec) TableName() string

type ContainerTmpfs added in v0.2.0

type ContainerTmpfs struct {
	// Target 是容器内的挂载路径(绝对路径)。
	Target string
	// Mode 是挂载权限,默认 1777,可写为 700 等。
	Mode string
	// UID/GID 是挂载点(tmpfs 根目录)的属主;为空时使用运行时默认(root)。
	//
	// 以非 root 用户运行并挂 HOME 时必须设置,否则容器用户无法写入 HOME。
	UID string
	GID string
}

ContainerTmpfs 描述一个内存盘挂载(对应 docker --tmpfs / HostConfig.Tmpfs)。

type ContainerVolume

type ContainerVolume struct {
	Source string
	Target string
	Mode   string
	// Type 可选:值为 "file" 时源路径按文件创建,否则按目录创建。
	Type  string
	Owner string
}

type ContextKey

type ContextKey string

ContextKey defines a type for context keys to avoid string collision

const (
	// TenantIDContextKey is the context key for tenant ID
	TenantIDContextKey ContextKey = "TenantID"
	// TenantInfoContextKey is the context key for tenant information
	TenantInfoContextKey ContextKey = "TenantInfo"
	ReqContextKey        ContextKey = "RequestContext"
	// RequestIDContextKey is the context key for request ID
	RequestIDContextKey ContextKey = "RequestID"
	// LoggerContextKey is the context key for logger
	LoggerContextKey ContextKey = "Logger"
	// UserContextKey is the context key for user information
	UserContextKey ContextKey = "User"
	// UserIDContextKey is the context key for user ID
	UserIDContextKey ContextKey = "UserID"
	// SessionTenantIDContextKey is the context key for session owner's tenant ID.
	// When set (e.g. in pipeline with shared agent), session/message lookups use this instead of TenantIDContextKey.
	SessionTenantIDContextKey ContextKey = "SessionTenantID"
	// EmbedQueryContextKey is the context key for embedding query text
	EmbedQueryContextKey ContextKey = "EmbedQuery"
	// LanguageContextKey is the context key for user language preference (e.g. "zh-CN", "en-US")
	LanguageContextKey ContextKey = "Language"
	// LangfuseTraceContextKey carries the active Langfuse *Trace across the
	// request lifecycle. Defined here (not inside the langfuse package) so
	// that logger.CloneContext can preserve it without importing langfuse.
	LangfuseTraceContextKey ContextKey = "LangfuseTrace"
)

func (ContextKey) String

func (c ContextKey) String() string

String returns the string representation of the context key

type CreateDatasetRequest added in v0.1.4

type CreateDatasetRequest struct {
	DatasetName string `json:"dataset_name" binding:"required"`
	// DatasetKey is optional; leave it empty for ordinary user datasets.
	DatasetKey  string `json:"dataset_key"`
	Description string `json:"description"`
	Metadata    string `json:"metadata"`
}

CreateDatasetRequest is the payload for creating a dataset. The primary key is generated by the application, callers only provide business fields.

func (*CreateDatasetRequest) ToDataset added in v0.1.4

func (r *CreateDatasetRequest) ToDataset() *Dataset

ToDataset converts the request into a Dataset entity. ID and audit fields are intentionally left zero so that BeforeCreate generates them.

type CursorPageResult

type CursorPageResult struct {
	Data       interface{} `json:"data"`
	PageSize   int         `json:"page_size"`
	NextCursor string      `json:"next_cursor,omitempty"`
	HasMore    bool        `json:"has_more"`
	SortBy     string      `json:"sort_by,omitempty"`
}

CursorPageResult represents cursor pagination result.

func NewCursorPageResult

func NewCursorPageResult(page *CursorPagination, data interface{}, nextCursor string, hasMore bool) *CursorPageResult

NewCursorPageResult creates a new cursor pagination result.

type CursorPagination

type CursorPagination struct {
	// Cursor for next page, empty means first page.
	Cursor string `form:"cursor" json:"cursor" binding:"omitempty"`
	// Sort field, for example: published_at, created_at, updated_at.
	SortBy string `form:"sort_by" json:"sort_by" binding:"omitempty"`
	// Page size.
	PageSize int `form:"page_size" json:"page_size" binding:"omitempty,min=1,max=1000"`
}

CursorPagination represents lazy-loading cursor pagination parameters.

func (*CursorPagination) GetPageSize

func (p *CursorPagination) GetPageSize() int

GetPageSize gets the page size, default is 20.

func (*CursorPagination) GetSortBy

func (p *CursorPagination) GetSortBy() string

GetSortBy gets the sort field, default is published_at.

type Dataset

type Dataset struct {
	ID int64 `json:"id,string" gorm:"primaryKey;type:bigint;autoIncrement:false"`

	DatasetName string `json:"dataset_name" gorm:"type:varchar(255)"`

	// DatasetKey is a stable business key used to look up well-known datasets
	// the system provisions on demand, e.g. DatasetKeyDatabases ("DATABASES")
	// for the project's reference database directory. User-created datasets
	// leave it empty. In practice it is unique per project (go_dataset itself
	// has no project column; the binding lives in go_project_dataset).
	DatasetKey string `json:"dataset_key" gorm:"type:varchar(64);index"`

	Description string `json:"description" gorm:"type:text"`

	Metadata string `json:"metadata" gorm:"type:text"`

	// Path is the dataset workspace directory (utils.GetDatasetDir). It is
	// derived at read time from the active project and is never persisted.
	Path string `json:"path,omitempty" gorm:"-"`

	CreatedAt time.Time `json:"created_at"`

	UpdatedAt time.Time `json:"updated_at"`
}

func (*Dataset) BeforeCreate

func (t *Dataset) BeforeCreate(_ *gorm.DB) error

func (Dataset) TableName

func (Dataset) TableName() string

type DatasetAssay added in v0.1.5

type DatasetAssay struct {
	ID int64 `json:"id,string" gorm:"primaryKey;type:bigint;autoIncrement:false"`

	DatasetID int64 `json:"dataset_id,string" gorm:"index;not null"`

	AssayID int64 `json:"assay_id,string" gorm:"index;not null"`

	CreatedAt time.Time `json:"created_at"`
}

DatasetAssay is the join table binding an Assay into a Dataset (go_dataset_assay). A dataset binds directly to the Assay; the assay's files follow it (go_file.assay_id), so every project-scoped query joins go_dataset_assay -> go_assay to filter on dataset_id. The same assay can be bound to multiple datasets.

func (*DatasetAssay) BeforeCreate added in v0.1.5

func (t *DatasetAssay) BeforeCreate(_ *gorm.DB) error

func (DatasetAssay) TableName added in v0.1.5

func (DatasetAssay) TableName() string

type DatasetDirFile added in v0.2.0

type DatasetDirFile struct {
	// Name is the file's base name.
	Name string `json:"name"`
	// RelativePath is the path relative to the dataset directory, using "/" as
	// the separator so the value is stable across platforms.
	RelativePath string `json:"relative_path"`
	// Path is the absolute path stored on go_file.path when the file is
	// imported.
	Path string `json:"path"`
	// Format is the lower-cased extension without the leading dot.
	Format string `json:"format"`
	Size   int64  `json:"size"`
	// ModTime is the physical file's modification time.
	ModTime string `json:"mod_time"`
	// Added reports whether a file with this path is already bound to the
	// dataset (go_file.path + go_dataset_file.dataset_id).
	Added bool `json:"added"`
}

DatasetDirFile describes one physical file discovered under a dataset's workspace directory (utils.GetDatasetDir). It is the read model of /data/dataset/dir-files and the input of the batch directory import.

type DatasetDirFilesResponse added in v0.2.0

type DatasetDirFilesResponse struct {
	Path  string            `json:"path"`
	Files []*DatasetDirFile `json:"files"`
}

DatasetDirFilesResponse is the payload of /data/dataset/dir-files: the dataset workspace directory path plus every file found in it.

type DatasetFile

type DatasetFile struct {
	ID int64 `json:"id,string" gorm:"primaryKey;type:bigint;autoIncrement:false"`

	DatasetID int64 `json:"dataset_id,string" gorm:"index;not null"`

	FileID int64 `json:"file_id,string" gorm:"index;not null"`

	CreatedAt time.Time `json:"created_at"`
}

DatasetFile is the pure join row binding a File to a Dataset. The file's role lives on the file itself (go_file.role), not here, so this row only carries the two foreign keys and the creation timestamp.

func (*DatasetFile) BeforeCreate

func (t *DatasetFile) BeforeCreate(_ *gorm.DB) error

func (DatasetFile) TableName

func (DatasetFile) TableName() string

type File

type File struct {
	ID int64 `json:"id,string" gorm:"primaryKey;type:bigint;autoIncrement:false"`

	FileName string `json:"file_name" gorm:"type:varchar(255)"`

	Path string `json:"path" gorm:"type:text;not null"`

	Format string `json:"format" gorm:"type:varchar(64)"`

	// AssayID owns the file (int64 PK of go_assay). 0 means the file is not
	// owned by any assay.
	AssayID int64 `json:"assay_id,string" gorm:"type:bigint;index"`

	// FileKey is the file's key inside its owning assay, e.g. FASTQ_R1 or BAM.
	// Analysis form inputs use it to map the file onto the matching key of
	// their resolver.accept_formats (see buildParseAnalysisResult).
	FileKey string `json:"file_key" gorm:"type:varchar(64)"`
	// Role is the role the file is published under in the workflow form's
	// analysis_result map, e.g. BAM / VCF / DEFAULT. A node output file takes it
	// from its output_patterns entry (see NodeCompletionCoordinator.recordNodeOutputFiles),
	// defaulting to dag.DefaultNodeOutputRole ("DEFAULT") when the pattern declares
	// none; resolveFormAnalysisResult groups the node output files by it so the
	// frontend reads them as dataMap[role] just like dataset files.
	Role           string `json:"role" gorm:"type:varchar(64);index"`
	AnalysisNodeID int64  `json:"analysis_node_id" gorm:"type:bigint;index"`

	Size int64 `json:"size"`

	MD5 string `json:"md5" gorm:"type:varchar(64);index"`

	Storage string `json:"storage" gorm:"type:varchar(32);default:LOCAL"`

	Description string `json:"description" gorm:"type:text"`

	CreatedAt time.Time `json:"created_at"`

	UpdatedAt time.Time `json:"updated_at"`
}

File is a physical file. A file belongs to at most one Assay (Assay -> File is 1:N), so the binding lives directly on this row instead of a join table:

Project -> DatasetAssay -> Assay -> File

Files that are only attached to a dataset (never produced by an assay) keep AssayID == 0, which is why the column stays nullable.

func (*File) BeforeCreate

func (t *File) BeforeCreate(_ *gorm.DB) error

func (File) TableName

func (File) TableName() string

type FileByProjectRoleGroup

type FileByProjectRoleGroup struct {
	Role string `json:"role"`

	Items []*FileWithDatasetInfo `json:"items"`
}

type FileWithDatasetInfo

type FileWithDatasetInfo struct {
	ID int64 `json:"id,string"`

	// FileID mirrors the file's own primary key (go_file.id). It is kept so list
	// responses still carry a "file_id" the frontend can pass straight to the
	// by-id sheet endpoints; the entity no longer has a separate business id.
	FileID int64 `json:"file_id,string"`

	FileName string `json:"file_name"`

	Path string `json:"path"`

	Format string `json:"format"`

	AnalysisNodeID int64 `json:"analysis_node_id,string,omitempty"`

	Size int64 `json:"size"`

	MD5 string `json:"md5"`

	Storage string `json:"storage"`

	Description string `json:"description"`

	CreatedAt time.Time `json:"created_at"`

	UpdatedAt time.Time `json:"updated_at"`

	DatasetID string `json:"dataset_id"`

	DatasetName string `json:"dataset_name"`

	Role string `json:"role"`
}

type GatewayRoute

type GatewayRoute struct {
	RouteKey string `json:"route_key" gorm:"primaryKey;type:varchar(255)"`

	ContainerInstanceID int64 `json:"container_instance_id,string" gorm:"index"`

	PathPrefix   string `json:"path_prefix" gorm:"type:varchar(512);not null;uniqueIndex"`
	IsTrimPrefix *bool  `json:"is_trim_prefix" gorm:"not null;default:true"`
	BackendHost  string `json:"backend_host" gorm:"type:varchar(255);not null"`
	BackendPort  int    `json:"backend_port" gorm:"not null"`

	Metadata datatypes.JSON `json:"metadata" gorm:"type:json"`

	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`
}

func (GatewayRoute) TableName

func (GatewayRoute) TableName() string

type ImportAssayTSVRequest added in v0.1.5

type ImportAssayTSVRequest struct {
	DatasetID int64  `json:"dataset_id,string" binding:"required"`
	Content   string `json:"content" binding:"required"`
	ProjectID int64  `json:"-"`
}

ImportAssayTSVRequest is the payload of the assay TSV import: a target dataset plus the raw TSV text (an uploaded file or pasted content).

The header row names the columns. Columns that map onto an Assay field configure that entity (see the column map in the data service), e.g. sample_name / assay_type / assay_role / assay_desc; every other column is treated as a File whose FileKey is the column name and whose Path is the cell value — so new file columns (FASTQ_R3, BAM, ...) need no code change. All columns except sample_name are optional. ProjectID is filled in by the handler from the active project and is never sent by the client.

type ImportAssayTSVResult added in v0.1.5

type ImportAssayTSVResult struct {
	Rows          int `json:"rows"`
	AssaysCreated int `json:"assays_created"`
	AssaysUpdated int `json:"assays_updated"`
	FilesCreated  int `json:"files_created"`
	FilesUpdated  int `json:"files_updated"`
}

ImportAssayTSVResult summarises one import run: how many rows were processed and how many records were created versus updated.

type ImportDatasetDirFilesResult added in v0.2.0

type ImportDatasetDirFilesResult struct {
	Total    int      `json:"total"`
	Imported int      `json:"imported"`
	Skipped  int      `json:"skipped"`
	Failed   int      `json:"failed"`
	Errors   []string `json:"errors,omitempty"`
}

ImportDatasetDirFilesResult summarizes a batch import of the dataset directory: one entry per discovered file is either imported or skipped.

type JSONMap

type JSONMap map[string]any

func (JSONMap) MarshalJSON

func (m JSONMap) MarshalJSON() ([]byte, error)

func (*JSONMap) Scan

func (m *JSONMap) Scan(value any) error

func (JSONMap) Value

func (m JSONMap) Value() (driver.Value, error)

type JSONSlice

type JSONSlice []any

func (JSONSlice) MarshalJSON

func (s JSONSlice) MarshalJSON() ([]byte, error)

func (*JSONSlice) Scan

func (s *JSONSlice) Scan(value any) error

func (JSONSlice) Value

func (s JSONSlice) Value() (driver.Value, error)

type LLMConversation

type LLMConversation struct {
	ID int64 `json:"id,string" gorm:"primaryKey;type:bigint;autoIncrement:false"`

	ConversationID string `json:"conversation_id" gorm:"type:varchar(64);uniqueIndex;not null"`

	LLMSessionID int64 `json:"llm_session_id,string" gorm:"index;not null"`

	Role string `json:"role" gorm:"type:varchar(32);index;not null"`

	Content string `json:"content" gorm:"type:longtext"`

	Model string `json:"model" gorm:"type:varchar(255)"`

	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`
}

LLMConversation stores a single conversation entry under a session. We intentionally use LLMSessionID instead of GORM associations.

func (*LLMConversation) BeforeCreate

func (t *LLMConversation) BeforeCreate(_ *gorm.DB) error

func (LLMConversation) TableName

func (LLMConversation) TableName() string

type LLMSession

type LLMSession struct {
	ID int64 `json:"id,string" gorm:"primaryKey;type:bigint;autoIncrement:false"`

	ProjectID int64 `json:"project_id" gorm:"type:bigint;index;not null"`

	Title string `json:"title" gorm:"type:varchar(255)"`

	Status string `json:"status" gorm:"type:varchar(32);index;not null;default:ACTIVE"`

	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`
}

LLMSession stores a chat session and owner scope. Relation with conversation is maintained manually via LLMConversation.LLMSessionID.

func (*LLMSession) BeforeCreate

func (t *LLMSession) BeforeCreate(_ *gorm.DB) error

func (LLMSession) TableName

func (LLMSession) TableName() string

type Literature added in v0.1.2

type Literature struct {
	ID int64 `json:"id,string" gorm:"primaryKey;type:bigint;autoIncrement:false"`

	Title     string    `json:"title" gorm:"type:varchar(255)"`
	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`
}

Literature maps to the t_literature table. It represents a reference paper / literature entry. Only metadata (title) is persisted; the full text is stored as a file on disk, mirroring how ProjectReport stores its content.

The relationship between literature and projects is maintained manually via the project_literature mapping table; we intentionally do NOT use GORM association tags/relations here.

func (*Literature) BeforeCreate added in v0.1.2

func (t *Literature) BeforeCreate(_ *gorm.DB) error

func (Literature) TableName added in v0.1.2

func (Literature) TableName() string

type LiteratureDetail added in v0.2.0

type LiteratureDetail struct {
	Literature *Literature
	Content    string
}

LiteratureDetail 是文献详情:元信息 + 全文文件内容。

type LiteraturePoolItem added in v0.1.2

type LiteraturePoolItem struct {
	Literature
	Bound bool `json:"bound"`
}

LiteraturePoolItem carries a Literature together with whether it is already bound to the queried project. Used by the bind-literature picker.

type LoginRequest

type LoginRequest struct {
	Email    string `json:"email"    binding:"required,email"`
	Password string `json:"password" binding:"required,min=6"`
}

LoginRequest represents a login request

type LoginResponse

type LoginResponse struct {
	Success      bool   `json:"success"`
	Message      string `json:"message,omitempty"`
	User         *User  `json:"user,omitempty"`
	Token        string `json:"token,omitempty"`
	RefreshToken string `json:"refresh_token,omitempty"`
}

LoginResponse represents a login response

type OIDCAuthURLResponse

type OIDCAuthURLResponse struct {
	Success             bool   `json:"success"`
	ProviderDisplayName string `json:"provider_display_name,omitempty"`
	AuthorizationURL    string `json:"authorization_url,omitempty"`
	State               string `json:"state,omitempty"`
}

type OIDCCallbackResponse

type OIDCCallbackResponse struct {
	Success      bool   `json:"success"`
	Message      string `json:"message,omitempty"`
	User         *User  `json:"user,omitempty"`
	Token        string `json:"token,omitempty"`
	RefreshToken string `json:"refresh_token,omitempty"`
	IsNewUser    bool   `json:"is_new_user,omitempty"`
}

type OIDCConfigResponse

type OIDCConfigResponse struct {
	Success             bool   `json:"success"`
	Enabled             bool   `json:"enabled"`
	ProviderDisplayName string `json:"provider_display_name,omitempty"`
}

type OIDCUserInfo

type OIDCUserInfo struct {
	Subject  string                 `json:"subject,omitempty"`
	Username string                 `json:"username,omitempty"`
	Email    string                 `json:"email,omitempty"`
	Claims   map[string]interface{} `json:"claims,omitempty"`
}

type OperationType added in v0.2.0

type OperationType string

OperationType 描述 Agent 想要执行的操作类别。

未来可继续扩展(install_package / git_push / docker / kubernetes ...), 权限策略按类型决定 allow / deny / ask。

定义在 types 包是为了让 User.AgentConfig 能直接持有权限配置, 同时避免 types → agent 的循环依赖;agent 包以别名复用这些类型。

const (
	OperationRead         OperationType = "read"          // 读取文件
	OperationWrite        OperationType = "write"         // 写入 / 修改文件
	OperationDelete       OperationType = "delete"        // 删除文件
	OperationMove         OperationType = "move"          // 移动 / 重命名文件
	OperationExecute      OperationType = "execute"       // 执行命令 / 脚本
	OperationNetwork      OperationType = "network"       // 网络访问
	OperationAnalysisNode OperationType = "analysis_node" // 运行分析节点(区别于直接执行 shell / 脚本)
)

type OutboxEvent

type OutboxEvent struct {
	ID int64 `json:"id,string" gorm:"primaryKey;type:bigint;autoIncrement:false"`

	Type string `json:"type" gorm:"type:varchar(128);index;not null"`

	Payload datatypes.JSON `json:"payload" gorm:"type:json;not null"`

	Status string `json:"status" gorm:"type:varchar(32);index;not null;default:pending"` // pending / sent

	SentAt *time.Time `json:"sent_at"`

	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`
}

func (*OutboxEvent) BeforeCreate

func (t *OutboxEvent) BeforeCreate(_ *gorm.DB) error

func (OutboxEvent) TableName

func (OutboxEvent) TableName() string

type PageResult

type PageResult struct {
	Total    int64       `json:"total"`     // Total number of records
	Page     int         `json:"page"`      // Current page number
	PageSize int         `json:"page_size"` // Page size
	Data     interface{} `json:"data"`      // Data
}

PageResult represents the pagination query result

func NewPageResult

func NewPageResult(total int64, page *Pagination, data interface{}) *PageResult

NewPageResult creates a new pagination result

type Pagination

type Pagination struct {
	// Page
	Page int `form:"page"      json:"page"      binding:"omitempty,min=1"`
	// Page size
	PageSize int `form:"page_size" json:"page_size" binding:"omitempty,min=1,max=1000"`
}

Pagination represents the pagination parameters

func (*Pagination) GetPage

func (p *Pagination) GetPage() int

GetPage gets the page number, default is 1

func (*Pagination) GetPageSize

func (p *Pagination) GetPageSize() int

GetPageSize gets the page size, default is 20

func (*Pagination) Limit

func (p *Pagination) Limit() int

Limit gets the limit for database query

func (*Pagination) Offset

func (p *Pagination) Offset() int

Offset gets the offset for database query

type PermissionDecision added in v0.2.0

type PermissionDecision string

PermissionDecision 是权限策略 / 决策结果。

const (
	DecisionAllow PermissionDecision = "allow" // 允许执行
	DecisionDeny  PermissionDecision = "deny"  // 拒绝执行
	DecisionAsk   PermissionDecision = "ask"   // 需要人工确认
)

type Project

type Project struct {
	ID int64 `json:"id,string" gorm:"primaryKey;type:bigint;autoIncrement:false"`
	// ID           uint           `json:"id" gorm:"primaryKey;autoIncrement"`
	ProjectName  string         `json:"project_name" gorm:"type:varchar(255)"`
	MetadataForm string         `json:"metadata_form" gorm:"type:text"`
	Research     string         `json:"research" gorm:"type:text"`
	Parameter    string         `json:"parameter" gorm:"type:text"`
	Mounts       datatypes.JSON `json:"mounts" gorm:"type:json"`
	Env          datatypes.JSON `json:"env" gorm:"type:json"`

	Description string    `json:"description" gorm:"type:text"`
	CreatedAt   time.Time `json:"created_at"`
	UpdatedAt   time.Time `json:"updated_at"`
}

Project maps to Python brave's t_project table.

func (*Project) BeforeCreate

func (t *Project) BeforeCreate(_ *gorm.DB) error

func (Project) TableName

func (Project) TableName() string

type ProjectDataset

type ProjectDataset struct {
	ID int64 `json:"id,string" gorm:"primaryKey;type:bigint;autoIncrement:false"`

	ProjectID int64 `json:"project_id,string" gorm:"index;not null"`

	DatasetID int64 `json:"dataset_id,string" gorm:"index;not null"`

	// Path is the bound dataset's workspace directory
	// (utils.GetDatasetDir(baseDir, project_id, dataset_id)). It is derived at
	// read time and is never persisted.
	Path string `json:"path,omitempty" gorm:"-"`

	CreatedAt time.Time `json:"created_at"`
}

func (*ProjectDataset) BeforeCreate

func (t *ProjectDataset) BeforeCreate(_ *gorm.DB) error

func (ProjectDataset) TableName

func (ProjectDataset) TableName() string

type ProjectListItem

type ProjectListItem struct {
	Project
	ShareCode    string `json:"share_code"`
	ShareEnabled bool   `json:"share_enabled"`
}

ProjectListItem carries a Project together with the sharing settings of the current user, taken from the user_project mapping table.

type ProjectLiterature added in v0.1.2

type ProjectLiterature struct {
	ID           uint      `json:"id" gorm:"primaryKey;autoIncrement"`
	ProjectID    int64     `` /* 142-byte string literal not displayed */
	LiteratureID int64     `` /* 148-byte string literal not displayed */
	CreatedAt    time.Time `json:"created_at"`
}

ProjectLiterature is a manual many-to-many mapping table between projects and literatures. We intentionally do not use GORM association tags/relations.

func (ProjectLiterature) TableName added in v0.1.2

func (ProjectLiterature) TableName() string

type ProjectReport

type ProjectReport struct {
	ID        int64     `json:"id,string" gorm:"primaryKey;type:bigint;autoIncrement:false"`
	ProjectID int64     `json:"project_id,string" gorm:"type:bigint;not null;index"`
	Title     string    `json:"title" gorm:"type:varchar(255)"`
	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`
}

ProjectReport 是一个报告容器,只保存标题等元信息,不再承载文件内容。 报告的内容由 ProjectReportItem 列表按顺序拼接而成。

func (*ProjectReport) BeforeCreate

func (t *ProjectReport) BeforeCreate(_ *gorm.DB) error

func (ProjectReport) TableName

func (ProjectReport) TableName() string

type ProjectReportCommitResult added in v0.2.0

type ProjectReportCommitResult struct {
	ReportID  string `json:"report_id"`
	ProjectID string `json:"project_id"`
	// Committed 本次是否真的产生了新提交(工作区干净时为 false,不产生空提交)。
	Committed bool `json:"committed"`
	// Commit 提交后的 HEAD hash。
	Commit string `json:"commit,omitempty"`
	// CommitMessage 本次提交实际使用的 message(入参为空时为后端默认文案)。
	CommitMessage string `json:"commit_message"`
}

ProjectReportCommitResult 是「提交报告工作目录改动」的结果。

type ProjectReportGitDiff added in v0.2.0

type ProjectReportGitDiff struct {
	// ReportID / ProjectID 是报告与项目的数值主键(对外统一为字符串)。
	ReportID  string `json:"report_id"`
	ProjectID string `json:"project_id"`
	// RepoDir 是报告工作目录(绝对路径)。
	RepoDir string `json:"repo_dir"`
	// Initialized 报告目录是否已是 git 仓库;false 时没有可展示的 diff。
	Initialized bool `json:"initialized"`
	// HeadCommit 本地 HEAD 提交 hash(尚无提交时为空)。
	HeadCommit string `json:"head_commit,omitempty"`
	// HasChanges 工作区是否有未提交改动。
	HasChanges bool `json:"has_changes"`
	// Worktree 工作区相对本地 HEAD 的未提交改动(含未跟踪文件)。
	Worktree utils.GitDiffSection `json:"worktree"`
	// GitState 实时的本地 git 状态(是否初始化 / 是否有未提交改动)。
	GitState utils.ReportWorktreeGitState `json:"git_state"`
}

ProjectReportGitDiff 是报告工作目录(<baseDir>/data/<projectId>/report/<reportId>)的本地变化。

报告没有发布目标(store),因此只有「工作区相对本地 HEAD 的未提交改动」这一段, 不包含组件目录 diff 里的 Unpublished。字段命名与前端 git 组件保持一致, 便于报告与组件共用同一套 diff 视图与操作按钮。

type ProjectReportItem added in v0.1.5

type ProjectReportItem struct {
	ID              int64 `json:"id,string" gorm:"primaryKey;type:bigint;autoIncrement:false"`
	ProjectReportID int64 `json:"project_report_id,string" gorm:"column:project_report_id;type:bigint;index:idx_project_report_items_report"`
	// ParentID 指向同一报告下的父条目 ID,0 表示根节点。用于组织树形结构。
	ParentID  int64                      `json:"parent_id,string" gorm:"column:parent_id;type:bigint;index:idx_project_report_items_parent"`
	OwnerType ProjectReportItemOwnerType `json:"owner_type" gorm:"column:owner_type;type:varchar(32);index:idx_project_report_items_owner"`
	// OwnerID 指向 OwnerType 对应的主键。
	OwnerID   int64     `json:"owner_id,string" gorm:"column:owner_id;type:bigint;index:idx_project_report_items_owner"`
	SortOrder int       `json:"sort_order" gorm:"column:sort_order;default:0"`
	CreatedAt time.Time `json:"created_at" gorm:"column:created_at"`
	UpdatedAt time.Time `json:"updated_at" gorm:"column:updated_at"`

	// Title 是展示用标题。仅 OwnerType=custom 时由用户编辑并持久化;
	// 其他引用类型的标题由 owner 推导(读取时派生),写入时会清空,不落库。
	Title string `json:"title" gorm:"type:varchar(255)"`
	// Content 是自定义 markdown 正文,仅 OwnerType=custom 时持久化;
	// 其他引用类型不存储内容。
	Content string `json:"content" gorm:"type:longtext"`
}

ProjectReportItem 是 ProjectReport 下的一个内容条目,按 SortOrder 排序后拼接成报告正文。

func (*ProjectReportItem) BeforeCreate added in v0.1.5

func (t *ProjectReportItem) BeforeCreate(_ *gorm.DB) error

func (ProjectReportItem) TableName added in v0.1.5

func (ProjectReportItem) TableName() string

type ProjectReportItemContent added in v0.1.5

type ProjectReportItemContent struct {
	Title     string                     `json:"title"`
	Content   string                     `json:"content"`
	OwnerType ProjectReportItemOwnerType `json:"owner_type"`
}

ProjectReportItemContent 是 ProjectReportItem 渲染后的内容片段。 Title 为展示标题,Content 为正文。

正文里的图片一律是以数据目录为根的绝对路径(如 /34/analysis_node/100/200/output/a.png): 节点完成时会把 output.md 里的相对图片路径改写掉(见 dag.NodeCompletionCoordinator), 展示侧只需统一补上 /data-analysis 前缀,因此这里不再需要 Prefix。

func (ProjectReportItemContent) Render added in v0.1.5

func (c ProjectReportItemContent) Render() string

Render 将片段渲染为 markdown 小节;正文为空时返回空串。 正文已包含可供展示的图片绝对路径,渲染时不再做任何路径改写。

type ProjectReportItemOrder added in v0.1.5

type ProjectReportItemOrder struct {
	ID        int64
	ParentID  int64
	SortOrder int
}

ProjectReportItemOrder 描述拖拽重排后单个条目的目标位置(父节点与同级顺序)。

type ProjectReportItemOwnerType added in v0.1.5

type ProjectReportItemOwnerType string

ProjectReportItemOwnerType 标识 ProjectReportItem 指向的内容来源类型。

const (
	// ProjectReportItemOwnerAnalysis 指向 Analysis(nextflow 表)的 ID。
	ProjectReportItemOwnerAnalysis ProjectReportItemOwnerType = "analysis"
	// ProjectReportItemOwnerAnalysisNode 指向 AnalysisNode(analysis_nodes 表)的 ID。
	ProjectReportItemOwnerAnalysisNode ProjectReportItemOwnerType = "analysis_node"
	// ProjectReportItemOwnerAISummary 指向 AISummary 的 ID。
	ProjectReportItemOwnerAISummary ProjectReportItemOwnerType = "ai_summary"
	// ProjectReportItemOwnerCustom 是自定义内容条目,用于章节占位/自定义 markdown 段落。
	// 它不引用外部 owner,标题与正文由用户直接编辑并持久化在本表。
	ProjectReportItemOwnerCustom ProjectReportItemOwnerType = "custom"
)

func NormalizeProjectReportItemOwnerType added in v0.1.5

func NormalizeProjectReportItemOwnerType(t string) (ProjectReportItemOwnerType, bool)

NormalizeProjectReportItemOwnerType 校验并归一化 OwnerType。

type QueryDataset

type QueryDataset struct {
	ID *int64 `json:"id,string,omitempty"`

	DatasetName string `json:"dataset_name,omitempty"`

	DatasetKey string `json:"dataset_key,omitempty"`

	Description string `json:"description,omitempty"`

	Metadata string `json:"metadata,omitempty"`
}

QueryDataset defines optional dataset filters for list/page APIs.

func (*QueryDataset) GetDatasetKey added in v0.2.0

func (q *QueryDataset) GetDatasetKey() string

func (*QueryDataset) GetDatasetName

func (q *QueryDataset) GetDatasetName() string

func (*QueryDataset) GetDescription

func (q *QueryDataset) GetDescription() string

func (*QueryDataset) GetMetadata

func (q *QueryDataset) GetMetadata() string

type RegisterRequest

type RegisterRequest struct {
	Username string `json:"username" binding:"required,min=2,max=50"`
	Email    string `json:"email"    binding:"required,email"`
	Password string `json:"password" binding:"required,min=6"`
}

RegisterRequest represents a registration request

type RegisterResponse

type RegisterResponse struct {
	Success bool   `json:"success"`
	Message string `json:"message,omitempty"`
	User    *User  `json:"user,omitempty"`
}

RegisterResponse represents a registration response

type RequestContext

type RequestContext struct {
	User *User
}

type RuntimeVariable added in v0.1.4

type RuntimeVariable struct {
	Name        string                  `json:"name"`
	Value       string                  `json:"value"`
	Category    RuntimeVariableCategory `json:"category"`
	Description string                  `json:"description"`
	Source      RuntimeVariableSource   `json:"source"`
}

RuntimeVariable 是一条已求值的运行时变量,附带展示元数据。

type RuntimeVariableCategory added in v0.1.4

type RuntimeVariableCategory string

RuntimeVariableCategory 对运行时变量按领域分组,用于前端分类展示。

const (
	RuntimeVariableCategorySystem     RuntimeVariableCategory = "system"
	RuntimeVariableCategoryPackage    RuntimeVariableCategory = "package"
	RuntimeVariableCategoryProject    RuntimeVariableCategory = "project"
	RuntimeVariableCategoryWorkspace  RuntimeVariableCategory = "workspace"
	RuntimeVariableCategoryAppSession RuntimeVariableCategory = "app_session"
	RuntimeVariableCategoryDagNode    RuntimeVariableCategory = "dag_node"
)

type RuntimeVariableDefinition added in v0.1.4

type RuntimeVariableDefinition struct {
	Name        string                  `json:"name"`
	Category    RuntimeVariableCategory `json:"category"`
	Description string                  `json:"description"`
	Source      RuntimeVariableSource   `json:"source"`
}

RuntimeVariableDefinition 是某个变量名的声明式元数据(单一事实来源)。

type RuntimeVariableSource added in v0.1.4

type RuntimeVariableSource string

RuntimeVariableSource 表示变量取值的来源。

const (
	RuntimeVariableSourceStatic   RuntimeVariableSource = "static"   // 固定/派生路径
	RuntimeVariableSourceEnv      RuntimeVariableSource = "env"      // 来自进程环境变量
	RuntimeVariableSourceDB       RuntimeVariableSource = "db"       // 来自 session/node/project 记录
	RuntimeVariableSourceComputed RuntimeVariableSource = "computed" // 运行时计算
)

type Script

type Script struct {
	// ID                  uint      `json:"id" gorm:"primaryKey;autoIncrement"`
	ID            int64  `json:"id,string" gorm:"primaryKey;type:bigint;autoIncrement:false"`
	StoreID       int64  `json:"store_id,string" gorm:"column:store_id;type:bigint"`
	ProjectID     int64  `json:"project_id,string" gorm:"column:project_id;type:bigint"`
	ScriptID      string `json:"component_id" gorm:"column:component_id;type:varchar(255)"`
	InstallKey    string `json:"install_key" gorm:"type:varchar(255)"`
	ComponentType string `json:"component_type" gorm:"type:varchar(255)"`
	// Name 是组件名称。Go / JSON 侧统一叫 name(列名暂不改动,仍为 component_name),
	// 因此这里必须显式指定 column,避免 gorm 按字段名推导出 name 列。
	Name                string `json:"name" gorm:"column:component_name;type:varchar(255)"`
	Description         string `json:"description" gorm:"type:longtext"`
	ComponentIDs        string `json:"component_ids" gorm:"type:longtext"`
	Img                 string `json:"img" gorm:"type:varchar(255)"`
	ContainerTemplateID int64  `json:"container_template_id,string" gorm:"column:container_template_id;type:bigint"`
	// IOSchema            string `json:"io_schema" gorm:"column:io_schema;type:longtext"`
	Tags       string `json:"tags" gorm:"type:varchar(255)"`
	FileType   string `json:"file_type" gorm:"type:varchar(255)"`
	ScriptType string `json:"script_type" gorm:"type:varchar(255)"`
	Category   string `json:"category" gorm:"type:varchar(255);default:default"`
	// Content        string `json:"content" gorm:"type:text"`
	OrderIndex int `json:"order_index"`

	// Version   string    `json:"version" gorm:"type:varchar(255)"`
	// Message   string    `json:"message" gorm:"type:longtext"`
	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`
}

func (*Script) BeforeCreate

func (t *Script) BeforeCreate(_ *gorm.DB) error

func (Script) TableName

func (Script) TableName() string

type ScriptContainerSnapshot

type ScriptContainerSnapshot struct {
	ScriptID      string `json:"script_id" gorm:"column:script_id"`
	ContainerID   int64  `json:"container_id,string" gorm:"column:container_id"`
	ContainerName string `json:"container_name" gorm:"column:container_name"`
	ImageName     string `json:"image_name" gorm:"column:image_name"`
}

ScriptContainerSnapshot is a read model for analysis node visualization. It flattens script -> container template definition/spec via SQL join. ContainerID is the go_container_template_definition primary key (the id scripts bind to); the full image name lives on the definition itself, so there is no separate image table here.

type ScriptJSONExportResponse

type ScriptJSONExportResponse struct {
	// Version 是导出文件格式版本(取值见 internal/exportcodec,如 exportcodec.VersionV1),
	// 写入 script.json 顶层;安装侧(InstallScript)据此路由到对应版本的 Codec。
	// 历史产物没有该字段,反序列化后为空字符串。
	Version  string         `json:"version"`
	ScriptID string         `json:"script_id"`
	Script   map[string]any `json:"script"`
	// 容器资产与 workflow.json 完全一致:两个按主键去重的平铺列表。
	// 脚本的 container_template_id 引用的是绑定行主键,绑定行通过 spec_id 引用运行配置,
	// 镜像名与拉取策略直接挂在绑定行上。两者均不含时间字段。
	ContainerTemplateSpecs       []ContainerTemplateSpec       `json:"container_template_specs,omitempty"`
	ContainerTemplateDefinitions []ContainerTemplateDefinition `json:"container_template_definitions,omitempty"`
}

type ScriptPageQuery

type ScriptPageQuery struct {
	IDs []int64 `json:"ids,omitempty"`

	ID *int64 `json:"id,string,omitempty"`

	ProjectID int64 `json:"project_id,string,omitempty"`

	ScriptID string `json:"script_id,omitempty"`

	Name string `json:"name,omitempty"`

	ScriptType string `json:"script_type,omitempty"`

	Category string `json:"category,omitempty"`

	InstallKey string `json:"install_key,omitempty"`

	Tags string `json:"tags,omitempty"`

	Keywords string `json:"keywords,omitempty"`

	ContainerTemplateID *int64 `json:"container_template_id,string,omitempty"`

	SortBy string `json:"sort_by,omitempty"`

	SortOrder string `json:"sort_order,omitempty"`
}

ScriptPageQuery defines optional filters and sorting for script pagination. New query fields should be added here and wired in repository applyFilters.

func (*ScriptPageQuery) GetCategory

func (q *ScriptPageQuery) GetCategory() string

func (*ScriptPageQuery) GetInstallKey

func (q *ScriptPageQuery) GetInstallKey() string

func (*ScriptPageQuery) GetKeywords

func (q *ScriptPageQuery) GetKeywords() string

func (*ScriptPageQuery) GetName added in v0.2.0

func (q *ScriptPageQuery) GetName() string

func (*ScriptPageQuery) GetScriptID

func (q *ScriptPageQuery) GetScriptID() string

func (*ScriptPageQuery) GetScriptType

func (q *ScriptPageQuery) GetScriptType() string

func (*ScriptPageQuery) GetSortColumn

func (q *ScriptPageQuery) GetSortColumn() string

func (*ScriptPageQuery) GetSortOrder

func (q *ScriptPageQuery) GetSortOrder() string

func (*ScriptPageQuery) GetTags

func (q *ScriptPageQuery) GetTags() string

type ScriptVersion

type ScriptVersion struct {
	Script
	// StoreVersion string `json:"store_version"`
	StorePath  string `json:"store_path"`
	ScriptPath string `json:"script_path"`
	// IOSchema 实时读取自脚本目录的 io_schema.json(不再是数据库字段)。
	IOSchema string `json:"io_schema"`
	// StoreURL string `json:"store_url"`
	// StoreMessage string `json:"store_message"`
	// GitState 由磁盘上的 git 元数据实时推导(不落库):
	// has_local_changes=true 表示本地有未发布改动,
	// has_store_changes=true 表示 store 有本地未同步的提交。
	GitState *utils.GitSyncState `json:"git_state,omitempty"`
}

type Store

type Store struct {
	ID int64 `json:"id,string" gorm:"primaryKey;autoIncrement"`

	// StoreID string `json:"store_id" gorm:"type:varchar(255);index"`
	// AppID       string         `json:"app_id" gorm:"type:varchar(255);index"`
	// workflow script
	StoreType string `json:"store_type" gorm:"type:varchar(255);index"`
	Name      string `json:"name" gorm:"type:varchar(255)"`
	Origin    string `json:"origin" gorm:"type:varchar(255)"`
	// URL 字段已删除:store 不再保存「远程仓库地址」。
	// 发布到远程(PublishStoreRemote)只把地址写进 store 裸仓库的 git remote 配置,
	// 下载来源地址同样可以从 clone 生成的 origin remote 读回,因此地址不再落库,
	// 避免数据库与仓库真实配置两份状态漂移。
	// 需要展示时读 Remotes(由磁盘实时推导)。
	// Status    string `json:"status" gorm:"type:varchar(255);index"`
	// PathName 是 store 目录在 storage.base_dir/store 下的相对标识,只在首次创建 store 时
	// 由 utils.GenerateStorePathName 生成随机串并固定下来:既不随 workflow_id / script_id 变化,
	// 也不来自下载源地址(历史数据可能仍是 workflow/script ID 或 "<owner>/<repo>",原样沿用)。
	// 绝对路径一律不落库,需要时用 utils.GetWorkflowOrScriptStoreDir(baseDir, PathName) 解析。
	PathName string `json:"path_name" gorm:"type:varchar(255)"`
	// StorePath 是 PathName 按当前 storage.base_dir 解析出的绝对目录,只在响应里返回。
	// 不落库(gorm:"-"),既避免 base_dir 迁移后库内路径失效,也保证与 PathName 单一来源一致。
	StorePath string `json:"store_path,omitempty" gorm:"-"`
	// Remotes 是 store 裸仓库上配置的远程仓库列表(github / gitee / origin ...),
	// 与 StorePath 一样只在响应里返回、不落库(gorm:"-"):发布到远程时写入的是
	// store 仓库的 git remote 配置,读取侧统一通过 utils.ReadGitRemotes 实时推导。
	Remotes  []utils.GitRemote `json:"remotes,omitempty" gorm:"-"`
	Category string            `json:"category" gorm:"type:varchar(255);index"`
	Tags     datatypes.JSON    `json:"tags" gorm:"type:json"`
	Img      string            `json:"img" gorm:"type:varchar(255)"`
	// PublishURLs datatypes.JSON `json:"publish_urls" gorm:"column:publish_urls;type:json"`
	Log string `json:"log" gorm:"type:longtext"`

	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`
}

func (*Store) BeforeCreate

func (t *Store) BeforeCreate(_ *gorm.DB) error

func (Store) TableName

func (Store) TableName() string

type StoreDTO

type StoreDTO struct {
	Store
	Installed   bool   `json:"installed"`
	InstalledID string `json:"installed_id,omitempty"`
}

type StorePageQuery

type StorePageQuery struct {
	StoreType string `json:"store_type"`
	Keywords  string `json:"keywords,omitempty"`
	SortBy    string `json:"sort_by,omitempty"`
	SortOrder string `json:"sort_order,omitempty"`
}

StorePageQuery defines required filters for store pagination.

func (*StorePageQuery) GetKeywords

func (q *StorePageQuery) GetKeywords() string

func (*StorePageQuery) GetSortColumn

func (q *StorePageQuery) GetSortColumn() string

func (*StorePageQuery) GetSortOrder

func (q *StorePageQuery) GetSortOrder() string

func (*StorePageQuery) GetStoreType

func (q *StorePageQuery) GetStoreType() string

type SummaryOwnerType added in v0.1.2

type SummaryOwnerType string

SummaryOwnerType 摘要所属对象的类型。

const (
	// SummaryOwnerAnalysis 摘要归属于 Analysis(nextflow 表)。
	SummaryOwnerAnalysis SummaryOwnerType = "analysis"
	// SummaryOwnerAnalysisNode 摘要归属于 AnalysisNode(analysis_nodes 表)。
	SummaryOwnerAnalysisNode SummaryOwnerType = "analysis_node"
)

type SummaryStatus added in v0.1.2

type SummaryStatus string

SummaryStatus 摘要生成状态。

const (
	SummaryStatusPending SummaryStatus = "pending"
	// SummaryStatusGenerating 生成中
	SummaryStatusGenerating SummaryStatus = "generating"
	// SummaryStatusSuccess 生成成功
	SummaryStatusSuccess SummaryStatus = "success"
	// SummaryStatusFailed 生成失败
	SummaryStatusFailed SummaryStatus = "failed"
)

type TerminalAppSessionInput added in v0.2.0

type TerminalAppSessionInput struct {
	UserID              int64
	ProjectID           int64
	ContainerTemplateID int64
	AgentSessionID      int64
	Name                string
	WorkspacePath       string
	Persistent          bool
}

TerminalAppSessionInput 是「按容器模板新建终端会话」的入参。

终端会话就是 AppSession:AgentSessionID 区分 UI 手动创建(0)与 Agent 创建(>0), Persistent 决定会话能否在最后一个订阅者离开后继续存活。

type TerminalSessionStatus added in v0.2.0

type TerminalSessionStatus string

TerminalSessionStatus 是终端会话在持久层的状态。

const (
	// TerminalSessionStatusRunning 表示会话对应的容器仍然存活。
	TerminalSessionStatusRunning TerminalSessionStatus = "running"
	// TerminalSessionStatusClosed 表示会话已被显式关闭或回收。
	TerminalSessionStatusClosed TerminalSessionStatus = "closed"
)

type UpdateDatasetRequest added in v0.1.4

type UpdateDatasetRequest struct {
	ID          int64  `json:"id,string" binding:"required"`
	DatasetName string `json:"dataset_name" binding:"required"`
	DatasetKey  string `json:"dataset_key"`
	Description string `json:"description"`
	Metadata    string `json:"metadata"`
}

UpdateDatasetRequest is the payload for updating a dataset. ID identifies the record to update and is always required.

func (*UpdateDatasetRequest) ToDataset added in v0.1.4

func (r *UpdateDatasetRequest) ToDataset() *Dataset

ToDataset converts the request into a Dataset entity for the update path.

type User

type User struct {
	// Unique identifier of the user
	ID int64 `json:"id,string" gorm:"primaryKey;type:bigint;autoIncrement:false"`
	// Username of the user
	Username string `json:"username"   gorm:"type:varchar(100);uniqueIndex;not null"`
	// Email address of the user
	Email string `json:"email"      gorm:"type:varchar(255);uniqueIndex;not null"`
	// Hashed password of the user
	PasswordHash string `json:"-"          gorm:"type:varchar(255);not null"`
	// Avatar URL of the user
	Avatar string `json:"avatar"     gorm:"type:varchar(500)"`
	// AgentConfig 用户的 Agent 配置(Profile + 权限策略),以 JSON 形式落库。
	AgentConfig UserAgentConfig `json:"agent_config" gorm:"serializer:json"`
	// Tenant ID that the user belongs to
	// TenantID uint64 `json:"tenant_id"  gorm:"index"`
	// Whether the user is active
	IsActive bool `json:"is_active"  gorm:"default:true"`
	// Whether the user can access all tenants (cross-tenant access)
	CanAccessAllTenants bool `json:"can_access_all_tenants" gorm:"default:false"`
	// Creation time of the user
	CreatedAt time.Time `json:"created_at"`
	// Last updated time of the user
	UpdatedAt time.Time `json:"updated_at"`
	// Deletion time of the user
	DeletedAt gorm.DeletedAt `json:"deleted_at" gorm:"index"`
}

User represents a user in the system

func (*User) BeforeCreate added in v0.2.0

func (u *User) BeforeCreate(_ *gorm.DB) error

BeforeCreate assigns a snowflake ID when the user is created without one.

func (*User) ToUserInfo

func (u *User) ToUserInfo() *UserInfo

ToUserInfo converts User to UserInfo (without sensitive data)

type UserAgentConfig added in v0.2.0

type UserAgentConfig struct {
	ProfileID   int64                                `json:"profile_id,omitempty,string"`
	Permissions map[OperationType]PermissionDecision `json:"permissions,omitempty"`
	// EnvID 是业务上下文对象 ID(如 project report id / analysis node id / analysis id)。
	EnvID string `json:"env_id,omitempty"`
	// EnvType 是业务上下文类型(见 handler 的 EnvType* 枚举,如 "projectReport" / "analysisNode")。
	EnvType string `json:"env_type,omitempty"`
}

UserAgentConfig 是存储在用户记录中的 Agent 配置快照(以 JSON 形式落库)。

它把「用户选择的 Profile」「用户自定义的权限策略」以及「当前业务上下文」合并为一处:

  • ProfileID:该用户选中的 AgentProfile ID(0 表示未选择,解析时走默认);
  • Permissions:按 OperationType 配置的决策。空 / 未命中某项时,该项回退到 agent.defaultPermissionPolicy 的默认决策;
  • EnvID / EnvType:当前业务上下文(llmEnv)。由前端在进入某个业务页面时通过 /auth/agent-config 更新到用户记录上,后端解析系统提示词模板变量与工作目录时 直接读取该用户配置,不再由请求体传入,保证上下文与登录用户一一对应。

func (UserAgentConfig) Env added in v0.2.0

func (c UserAgentConfig) Env() map[string]any

Env 把用户当前的业务上下文还原为 {id,type} 形式,供 RuntimeContextResolver 解析。 EnvType 为空时返回 nil,表示当前无业务上下文(回退到默认工作目录)。

func (UserAgentConfig) HasEnv added in v0.2.0

func (c UserAgentConfig) HasEnv() bool

HasEnv 报告用户当前是否绑定了业务上下文。

type UserBottomPanel added in v0.2.0

type UserBottomPanel struct {
	Open   bool            `json:"open"`
	Active string          `json:"active,omitempty"`
	Height int             `json:"height,omitempty"`
	Tabs   []UserBottomTab `json:"tabs,omitempty"`
}

UserBottomPanel 是主区域底部面板的完整状态。

Open = 面板是否展开(收起时只保留标签栏);Active = 当前激活标签的 Key; Height = 展开时的高度(px)。三个状态与标签列表一起落库,刷新后可原样恢复。

type UserBottomTab added in v0.2.0

type UserBottomTab struct {
	Key    string         `json:"key"`
	Kind   string         `json:"kind"`
	Title  string         `json:"title,omitempty"`
	Params map[string]any `json:"params,omitempty"`
}

UserBottomTab 是底部面板的一个标签页。

Kind 决定前端用哪个渲染器(terminal / log / …),Params 是该渲染器自己的参数 (终端为 {template_id}),因此新增底部面板类型不需要改后端表结构。

type UserInfo

type UserInfo struct {
	ID          int64           `json:"id,string"`
	Username    string          `json:"username"`
	Email       string          `json:"email"`
	Avatar      string          `json:"avatar"`
	AgentConfig UserAgentConfig `json:"agent_config"`
	// MenuConfig 是用户在「当前激活项目」下的菜单配置(主区域标签页 + 底部面板),
	// 数据存在 user_project.menu_config。字段名保持 menu_config 不变,前端无需改动。
	MenuConfig UserMenuConfig `json:"menu_config"`
	// AgentProfile 是 agent_config.ProfileID 对应的 Profile 摘要(DTO,按需填充,可能为空)。
	AgentProfile        *AgentProfileInfo `json:"agent_profile,omitempty"`
	TenantID            uint64            `json:"tenant_id"`
	IsActive            bool              `json:"is_active"`
	CanAccessAllTenants bool              `json:"can_access_all_tenants"`
	CreatedAt           time.Time         `json:"created_at"`
	UpdatedAt           time.Time         `json:"updated_at"`
}

UserInfo represents user information for API responses

type UserMenuConfig added in v0.2.0

type UserMenuConfig struct {
	Tabs []UserMenuTab `json:"tabs,omitempty"`
	// Bottom 为空表示底部面板没有打开的标签(前端据此不渲染面板)。
	Bottom *UserBottomPanel `json:"bottom,omitempty"`
}

UserMenuConfig 是「某用户在某项目下」的菜单配置(主区域标签页 + 底部面板), 以 JSON 形式落库在 user_project.menu_config。

用「有序数组」而不是「urls + titles 两张表」:顺序即标签栏顺序,标题跟着自己的 URL 走, 序列化 / 回填都是一次读写。

func (*UserMenuConfig) Normalize added in v0.2.0

func (c *UserMenuConfig) Normalize()

Normalize 清洗整份菜单配置(标签页 + 底部面板)。 调用方(handler)在写库前调用,避免把脏数据或超长字符串落库。

func (*UserMenuConfig) NormalizeBottom added in v0.2.0

func (c *UserMenuConfig) NormalizeBottom()

NormalizeBottom 清洗底部面板:去空白、去重(按 Key)、丢弃缺少 Kind 的项、按上限截断尾部, 并保证 Active 指向一个真实存在的标签;没有标签时把 Bottom 置空,避免前端渲染空面板。

func (*UserMenuConfig) NormalizeTabs added in v0.2.0

func (c *UserMenuConfig) NormalizeTabs()

NormalizeTabs 清洗主区域标签页列表:去空白、去重(保留首次出现)、丢弃根路由,并按上限截断尾部。

type UserMenuTab added in v0.2.0

type UserMenuTab struct {
	URL   string `json:"url"`
	Title string `json:"title,omitempty"`
}

UserMenuTab 是主区域一个标签页的状态。

URL 是标签页对应的路由地址(pathname + search),前端直接 navigate(URL) 即可切换; Title 是该标签页最近一次登记的显示名(如分析节点名),可为空 —— 为空时前端回退到静态标题规则。

type UserProject

type UserProject struct {
	ID     uint  `json:"id" gorm:"primaryKey;autoIncrement"`
	UserID int64 `json:"user_id,string" gorm:"type:bigint;not null;index:idx_user_project_user;uniqueIndex:idx_user_project_unique,priority:1"`
	// ProjectID 指向 t_project.id。
	ProjectID int64 `` /* 148-byte string literal not displayed */
	IsActive  bool  `json:"is_active" gorm:"default:false"`

	// ShareCode is generated when the owner enables project sharing. Other users
	// can use it to look up the project and gain access.
	ShareCode string `json:"share_code" gorm:"type:varchar(64);index"`
	// ShareEnabled toggles whether the project can be shared via ShareCode.
	ShareEnabled bool `json:"share_enabled" gorm:"default:false"`
	// MenuConfig 是「该用户在这个项目下」的菜单配置(主区域标签页 + 底部面板)。
	// 标签页、终端等界面状态都是项目维度的,所以随 user_project 一起落库。
	MenuConfig UserMenuConfig `json:"menu_config" gorm:"serializer:json"`
	CreatedAt  time.Time      `json:"created_at"`
}

UserProject is a manual many-to-many mapping table between users and projects. We intentionally do not use GORM association tags/relations.

func (UserProject) TableName

func (UserProject) TableName() string

type Workflow

type Workflow struct {
	// ID                 uint           `json:"id" gorm:"primaryKey;autoIncrement"`
	ID        int64          `json:"id,string" gorm:"primaryKey;type:bigint;autoIncrement:false"`
	ProjectID int64          `json:"project_id,string" gorm:"column:project_id;type:bigint"`
	StoreID   int64          `json:"store_id,string" gorm:"column:store_id;type:bigint"`
	Name      string         `json:"name" gorm:"type:varchar(255)"`
	Img       string         `json:"img" gorm:"type:varchar(255)"`
	Tags      datatypes.JSON `json:"tags" gorm:"type:json"`
	// URL                string         `json:"url" gorm:"column:url;type:varchar(255)"`
	Category    string `json:"category" gorm:"type:varchar(255);default:default"`
	Description string `json:"description" gorm:"type:longtext"`
	Prompt      string `json:"prompt" gorm:"type:longtext"`
	// DagDefinition      string         `json:"dag_definition" gorm:"column:dag_definition;type:longtext"`
	WorkflowID         string         `json:"workflow_id" gorm:"column:relation_id;type:varchar(255)"`
	RelationType       string         `json:"relation_type" gorm:"type:varchar(255)"`
	InstallKey         string         `json:"install_key" gorm:"type:varchar(255)"`
	ModuleID           string         `json:"component_id" gorm:"column:component_id;type:varchar(255)"`
	ContainerID        string         `json:"container_id" gorm:"type:varchar(255)"`
	ParentComponentID  string         `json:"parent_component_id" gorm:"type:varchar(255)"`
	InputComponentIDs  datatypes.JSON `json:"input_component_ids" gorm:"type:json"`
	OutputComponentIDs datatypes.JSON `json:"output_component_ids" gorm:"type:json"`
	OrderIndex         int            `json:"order_index"`
	// Version            string         `json:"version" gorm:"type:varchar(255)"`
	// Message   string    `json:"message" gorm:"type:longtext"`
	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`
}

func (*Workflow) BeforeCreate

func (t *Workflow) BeforeCreate(_ *gorm.DB) error

func (Workflow) TableName

func (Workflow) TableName() string

type WorkflowJSONExportResponse

type WorkflowJSONExportResponse struct {
	// Version 是导出文件格式版本(取值见 internal/exportcodec,如 exportcodec.VersionV1),
	// 写入 workflow.json 顶层;安装侧(InstallWorkflow)据此路由到对应版本的 Codec。
	// 历史产物没有该字段,反序列化后为空字符串。
	Version string `json:"version"`
	// Path               string           `json:"path"`
	WorkflowID string           `json:"workflow_id"`
	Workflow   map[string]any   `json:"workflow"`
	Scripts    []map[string]any `json:"scripts"`
	// 容器资产是两个按主键去重的平铺列表,与 script.json 完全一致。
	// ContainerTemplateSpecs 是运行配置(definition.spec_id 指向它);
	// ContainerTemplateDefinitions 是绑定行(主键即脚本 container_template_id,
	// 镜像名与拉取策略直接挂在绑定行上)。两者均不含时间字段。
	ContainerTemplateSpecs       []ContainerTemplateSpec       `json:"container_template_specs"`
	ContainerTemplateDefinitions []ContainerTemplateDefinition `json:"container_template_definitions"`
}

type WorkflowPageQuery

type WorkflowPageQuery struct {
	IDs []uint `json:"ids,omitempty"`

	ID *uint `json:"id,omitempty"`

	ProjectID int64 `json:"project_id,string,omitempty"`

	WorkflowID string `json:"workflow_id,omitempty"`

	Name string `json:"name,omitempty"`

	Category string `json:"category,omitempty"`

	InstallKey string `json:"install_key,omitempty"`

	ModuleID string `json:"module_id,omitempty"`

	RelationType string `json:"relation_type,omitempty"`

	Tags string `json:"tags,omitempty"`

	Keywords string `json:"keywords,omitempty"`

	SortBy string `json:"sort_by,omitempty"`

	SortOrder string `json:"sort_order,omitempty"`
}

WorkflowPageQuery defines optional filters and sorting for workflow pagination.

func (*WorkflowPageQuery) GetCategory

func (q *WorkflowPageQuery) GetCategory() string

func (*WorkflowPageQuery) GetInstallKey

func (q *WorkflowPageQuery) GetInstallKey() string

func (*WorkflowPageQuery) GetKeywords

func (q *WorkflowPageQuery) GetKeywords() string

func (*WorkflowPageQuery) GetModuleID

func (q *WorkflowPageQuery) GetModuleID() string

func (*WorkflowPageQuery) GetName

func (q *WorkflowPageQuery) GetName() string

func (*WorkflowPageQuery) GetRelationType

func (q *WorkflowPageQuery) GetRelationType() string

func (*WorkflowPageQuery) GetSortColumn

func (q *WorkflowPageQuery) GetSortColumn() string

func (*WorkflowPageQuery) GetSortOrder

func (q *WorkflowPageQuery) GetSortOrder() string

func (*WorkflowPageQuery) GetTags

func (q *WorkflowPageQuery) GetTags() string

func (*WorkflowPageQuery) GetWorkflowID

func (q *WorkflowPageQuery) GetWorkflowID() string

type WorkflowVersion

type WorkflowVersion struct {
	// ID                 int64          `json:"id,string"`
	// ProjectID          int64          `json:"project_id,string"`
	// StoreID            int64          `json:"store_id,string"`
	// Name               string         `json:"name"`
	// Img                string         `json:"img"`
	// Tags               datatypes.JSON `json:"tags"`
	// URL                string         `json:"url"`
	// Category           string         `json:"category"`
	// Description        string         `json:"description"`
	// Prompt             string         `json:"prompt"`
	// DagDefinition      string         `json:"dag_definition"`
	// WorkflowID         string         `json:"relation_id"`
	// RelationType       string         `json:"relation_type"`
	// InstallKey         string         `json:"install_key"`
	// ModuleID           string         `json:"component_id"`
	// ContainerID        string         `json:"container_id"`
	// ParentComponentID  string         `json:"parent_component_id"`
	// InputComponentIDs  datatypes.JSON `json:"input_component_ids"`
	// OutputComponentIDs datatypes.JSON `json:"output_component_ids"`
	// OrderIndex         int            `json:"order_index"`
	// Version            string         `json:"version"`
	// UpdateInfo         string         `json:"update_info"`
	// CreatedAt          time.Time      `json:"created_at"`
	// UpdatedAt          time.Time      `json:"updated_at"`
	Workflow
	StorePath    string `json:"store_path"`
	WorkflowPath string `json:"workflow_path"`
	// DagDefinition 实时读取自工作流目录的 dag_definition.json(不再是数据库字段)。
	// 用于工作流可视化编辑与 DAG 运行时编译(见 GetWorkflowVisByWorkflowID / SaveWorkflow)。
	DagDefinition string `json:"dag_definition"`
	// IOSchema 实时读取自工作流目录的 io_schema.json(不再是数据库字段)。
	// 工作流级 inputs 用于运行工作流时生成 formJson(见 GetFormJSONByWorkflowID)。
	IOSchema string `json:"io_schema"`
	// StoreURL     string `json:"store_url"`
	// StoreMessage string `json:"store_message"`
	// StoreVersion string `json:"store_version"`
	// GitState 由磁盘上的 git 元数据实时推导(不落库):
	// has_local_changes=true 表示本地有未发布改动,
	// has_store_changes=true 表示 store 有本地未同步的提交。
	GitState *utils.GitSyncState `json:"git_state,omitempty"`
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL