package run import ( "sort" "time" ) // ===== 请求 ===== // CreateRunProfileReq 是创建 run profile 的请求体。Env 为明文,服务端加密落库。 type CreateRunProfileReq struct { Slug string `json:"slug"` Name string `json:"name"` Description string `json:"description"` Command string `json:"command"` Args []string `json:"args"` Env map[string]string `json:"env"` Enabled *bool `json:"enabled"` // 省略默认为 true } // UpdateRunProfileReq 是部分更新请求:nil 字段表示不修改。 type UpdateRunProfileReq struct { Slug *string `json:"slug"` Name *string `json:"name"` Description *string `json:"description"` Command *string `json:"command"` Args *[]string `json:"args"` Env *map[string]string `json:"env"` Enabled *bool `json:"enabled"` } // ===== 响应 ===== // RunProfileResp 是 profile 的对外表示。env 不回传明文,仅回 env_keys。 type RunProfileResp struct { ID string `json:"id"` WorkspaceID string `json:"workspace_id"` Slug string `json:"slug"` Name string `json:"name"` Description string `json:"description"` Command string `json:"command"` Args []string `json:"args"` EnvKeys []string `json:"env_keys"` Enabled bool `json:"enabled"` Status string `json:"status"` StartedAt *string `json:"started_at"` LastStartedAt *string `json:"last_started_at"` LastExitCode *int32 `json:"last_exit_code"` LastError string `json:"last_error"` CreatedAt string `json:"created_at"` UpdatedAt string `json:"updated_at"` } // RunStatusResp 是 start/stop/restart/status 的轻量返回。 type RunStatusResp struct { Status string `json:"status"` StartedAt *string `json:"started_at"` LastExitCode *int32 `json:"last_exit_code"` LastError string `json:"last_error"` } // LogLineResp 是日志 tail 的返回行。 type LogLineResp struct { ID int64 `json:"id"` Level string `json:"level"` Text string `json:"text"` TS string `json:"ts"` } // ===== 转换 helper ===== func fmtTime(t time.Time) string { return t.UTC().Format(time.RFC3339) } func fmtTimePtr(t *time.Time) *string { if t == nil { return nil } s := t.UTC().Format(time.RFC3339) return &s } func buildRunProfileResp(p *RunProfile, envKeys []string, status RunStatus, startedAt *time.Time) RunProfileResp { args := p.Args if args == nil { args = []string{} } if envKeys == nil { envKeys = []string{} } return RunProfileResp{ ID: p.ID.String(), WorkspaceID: p.WorkspaceID.String(), Slug: p.Slug, Name: p.Name, Description: p.Description, Command: p.Command, Args: args, EnvKeys: envKeys, Enabled: p.Enabled, Status: string(status), StartedAt: fmtTimePtr(startedAt), LastStartedAt: fmtTimePtr(p.LastStartedAt), LastExitCode: p.LastExitCode, LastError: p.LastError, CreatedAt: fmtTime(p.CreatedAt), UpdatedAt: fmtTime(p.UpdatedAt), } } func sortedKeys(m map[string]string) []string { keys := make([]string, 0, len(m)) for k := range m { keys = append(keys, k) } sort.Strings(keys) return keys } func toLogLineResp(e *LogEnvelope) LogLineResp { return LogLineResp{ID: e.ID, Level: e.Level, Text: e.Text, TS: e.TS.UTC().Format(time.RFC3339)} }