Merge pull request #123 from AlanAlanAlanXu/main

添加一键dump所有用户的补全数据的api
This commit is contained in:
Yoko
2025-07-22 18:44:26 +08:00
committed by GitHub
19 changed files with 532 additions and 197 deletions

View File

@@ -1,6 +1,6 @@
// Code generated by Wire. DO NOT EDIT.
//go:generate go run github.com/google/wire/cmd/wire
//go:generate go run -mod=mod github.com/google/wire/cmd/wire
//go:build !wireinject
// +build !wireinject

View File

@@ -266,13 +266,14 @@ var (
{Name: "is_accept", Type: field.TypeBool, Default: false},
{Name: "program_language", Type: field.TypeString, Nullable: true},
{Name: "work_mode", Type: field.TypeString, Nullable: true},
{Name: "prompt", Type: field.TypeString, Nullable: true},
{Name: "completion", Type: field.TypeString, Nullable: true},
{Name: "code_lines", Type: field.TypeInt64, Nullable: true},
{Name: "input_tokens", Type: field.TypeInt64, Nullable: true},
{Name: "output_tokens", Type: field.TypeInt64, Nullable: true},
{Name: "is_suggested", Type: field.TypeBool, Default: false},
{Name: "source_code", Type: field.TypeString, Nullable: true},
{Name: "cursor_position", Type: field.TypeInt64, Nullable: true},
{Name: "cursor_position", Type: field.TypeJSON, Nullable: true},
{Name: "user_input", Type: field.TypeString, Nullable: true},
{Name: "created_at", Type: field.TypeTime},
{Name: "updated_at", Type: field.TypeTime},
@@ -287,13 +288,13 @@ var (
ForeignKeys: []*schema.ForeignKey{
{
Symbol: "tasks_models_tasks",
Columns: []*schema.Column{TasksColumns[17]},
Columns: []*schema.Column{TasksColumns[18]},
RefColumns: []*schema.Column{ModelsColumns[0]},
OnDelete: schema.SetNull,
},
{
Symbol: "tasks_users_tasks",
Columns: []*schema.Column{TasksColumns[18]},
Columns: []*schema.Column{TasksColumns[19]},
RefColumns: []*schema.Column{UsersColumns[0]},
OnDelete: schema.SetNull,
},

View File

@@ -9869,6 +9869,7 @@ type TaskMutation struct {
is_accept *bool
program_language *string
work_mode *string
prompt *string
completion *string
code_lines *int64
addcode_lines *int64
@@ -9878,8 +9879,7 @@ type TaskMutation struct {
addoutput_tokens *int64
is_suggested *bool
source_code *string
cursor_position *int64
addcursor_position *int64
cursor_position *map[string]interface{}
user_input *string
created_at *time.Time
updated_at *time.Time
@@ -10353,6 +10353,55 @@ func (m *TaskMutation) ResetWorkMode() {
delete(m.clearedFields, task.FieldWorkMode)
}
// SetPrompt sets the "prompt" field.
func (m *TaskMutation) SetPrompt(s string) {
m.prompt = &s
}
// Prompt returns the value of the "prompt" field in the mutation.
func (m *TaskMutation) Prompt() (r string, exists bool) {
v := m.prompt
if v == nil {
return
}
return *v, true
}
// OldPrompt returns the old "prompt" field's value of the Task entity.
// If the Task object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *TaskMutation) OldPrompt(ctx context.Context) (v string, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldPrompt is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldPrompt requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldPrompt: %w", err)
}
return oldValue.Prompt, nil
}
// ClearPrompt clears the value of the "prompt" field.
func (m *TaskMutation) ClearPrompt() {
m.prompt = nil
m.clearedFields[task.FieldPrompt] = struct{}{}
}
// PromptCleared returns if the "prompt" field was cleared in this mutation.
func (m *TaskMutation) PromptCleared() bool {
_, ok := m.clearedFields[task.FieldPrompt]
return ok
}
// ResetPrompt resets all changes to the "prompt" field.
func (m *TaskMutation) ResetPrompt() {
m.prompt = nil
delete(m.clearedFields, task.FieldPrompt)
}
// SetCompletion sets the "completion" field.
func (m *TaskMutation) SetCompletion(s string) {
m.completion = &s
@@ -10698,13 +10747,12 @@ func (m *TaskMutation) ResetSourceCode() {
}
// SetCursorPosition sets the "cursor_position" field.
func (m *TaskMutation) SetCursorPosition(i int64) {
m.cursor_position = &i
m.addcursor_position = nil
func (m *TaskMutation) SetCursorPosition(value map[string]interface{}) {
m.cursor_position = &value
}
// CursorPosition returns the value of the "cursor_position" field in the mutation.
func (m *TaskMutation) CursorPosition() (r int64, exists bool) {
func (m *TaskMutation) CursorPosition() (r map[string]interface{}, exists bool) {
v := m.cursor_position
if v == nil {
return
@@ -10715,7 +10763,7 @@ func (m *TaskMutation) CursorPosition() (r int64, exists bool) {
// OldCursorPosition returns the old "cursor_position" field's value of the Task entity.
// If the Task object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *TaskMutation) OldCursorPosition(ctx context.Context) (v int64, err error) {
func (m *TaskMutation) OldCursorPosition(ctx context.Context) (v map[string]interface{}, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldCursorPosition is only allowed on UpdateOne operations")
}
@@ -10729,28 +10777,9 @@ func (m *TaskMutation) OldCursorPosition(ctx context.Context) (v int64, err erro
return oldValue.CursorPosition, nil
}
// AddCursorPosition adds i to the "cursor_position" field.
func (m *TaskMutation) AddCursorPosition(i int64) {
if m.addcursor_position != nil {
*m.addcursor_position += i
} else {
m.addcursor_position = &i
}
}
// AddedCursorPosition returns the value that was added to the "cursor_position" field in this mutation.
func (m *TaskMutation) AddedCursorPosition() (r int64, exists bool) {
v := m.addcursor_position
if v == nil {
return
}
return *v, true
}
// ClearCursorPosition clears the value of the "cursor_position" field.
func (m *TaskMutation) ClearCursorPosition() {
m.cursor_position = nil
m.addcursor_position = nil
m.clearedFields[task.FieldCursorPosition] = struct{}{}
}
@@ -10763,7 +10792,6 @@ func (m *TaskMutation) CursorPositionCleared() bool {
// ResetCursorPosition resets all changes to the "cursor_position" field.
func (m *TaskMutation) ResetCursorPosition() {
m.cursor_position = nil
m.addcursor_position = nil
delete(m.clearedFields, task.FieldCursorPosition)
}
@@ -11030,7 +11058,7 @@ func (m *TaskMutation) Type() string {
// order to get all numeric fields that were incremented/decremented, call
// AddedFields().
func (m *TaskMutation) Fields() []string {
fields := make([]string, 0, 18)
fields := make([]string, 0, 19)
if m.task_id != nil {
fields = append(fields, task.FieldTaskID)
}
@@ -11055,6 +11083,9 @@ func (m *TaskMutation) Fields() []string {
if m.work_mode != nil {
fields = append(fields, task.FieldWorkMode)
}
if m.prompt != nil {
fields = append(fields, task.FieldPrompt)
}
if m.completion != nil {
fields = append(fields, task.FieldCompletion)
}
@@ -11109,6 +11140,8 @@ func (m *TaskMutation) Field(name string) (ent.Value, bool) {
return m.ProgramLanguage()
case task.FieldWorkMode:
return m.WorkMode()
case task.FieldPrompt:
return m.Prompt()
case task.FieldCompletion:
return m.Completion()
case task.FieldCodeLines:
@@ -11154,6 +11187,8 @@ func (m *TaskMutation) OldField(ctx context.Context, name string) (ent.Value, er
return m.OldProgramLanguage(ctx)
case task.FieldWorkMode:
return m.OldWorkMode(ctx)
case task.FieldPrompt:
return m.OldPrompt(ctx)
case task.FieldCompletion:
return m.OldCompletion(ctx)
case task.FieldCodeLines:
@@ -11239,6 +11274,13 @@ func (m *TaskMutation) SetField(name string, value ent.Value) error {
}
m.SetWorkMode(v)
return nil
case task.FieldPrompt:
v, ok := value.(string)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetPrompt(v)
return nil
case task.FieldCompletion:
v, ok := value.(string)
if !ok {
@@ -11282,7 +11324,7 @@ func (m *TaskMutation) SetField(name string, value ent.Value) error {
m.SetSourceCode(v)
return nil
case task.FieldCursorPosition:
v, ok := value.(int64)
v, ok := value.(map[string]interface{})
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
@@ -11326,9 +11368,6 @@ func (m *TaskMutation) AddedFields() []string {
if m.addoutput_tokens != nil {
fields = append(fields, task.FieldOutputTokens)
}
if m.addcursor_position != nil {
fields = append(fields, task.FieldCursorPosition)
}
return fields
}
@@ -11343,8 +11382,6 @@ func (m *TaskMutation) AddedField(name string) (ent.Value, bool) {
return m.AddedInputTokens()
case task.FieldOutputTokens:
return m.AddedOutputTokens()
case task.FieldCursorPosition:
return m.AddedCursorPosition()
}
return nil, false
}
@@ -11375,13 +11412,6 @@ func (m *TaskMutation) AddField(name string, value ent.Value) error {
}
m.AddOutputTokens(v)
return nil
case task.FieldCursorPosition:
v, ok := value.(int64)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.AddCursorPosition(v)
return nil
}
return fmt.Errorf("unknown Task numeric field %s", name)
}
@@ -11405,6 +11435,9 @@ func (m *TaskMutation) ClearedFields() []string {
if m.FieldCleared(task.FieldWorkMode) {
fields = append(fields, task.FieldWorkMode)
}
if m.FieldCleared(task.FieldPrompt) {
fields = append(fields, task.FieldPrompt)
}
if m.FieldCleared(task.FieldCompletion) {
fields = append(fields, task.FieldCompletion)
}
@@ -11455,6 +11488,9 @@ func (m *TaskMutation) ClearField(name string) error {
case task.FieldWorkMode:
m.ClearWorkMode()
return nil
case task.FieldPrompt:
m.ClearPrompt()
return nil
case task.FieldCompletion:
m.ClearCompletion()
return nil
@@ -11508,6 +11544,9 @@ func (m *TaskMutation) ResetField(name string) error {
case task.FieldWorkMode:
m.ResetWorkMode()
return nil
case task.FieldPrompt:
m.ResetPrompt()
return nil
case task.FieldCompletion:
m.ResetCompletion()
return nil

View File

@@ -257,15 +257,15 @@ func init() {
// task.DefaultIsAccept holds the default value on creation for the is_accept field.
task.DefaultIsAccept = taskDescIsAccept.Default.(bool)
// taskDescIsSuggested is the schema descriptor for is_suggested field.
taskDescIsSuggested := taskFields[13].Descriptor()
taskDescIsSuggested := taskFields[14].Descriptor()
// task.DefaultIsSuggested holds the default value on creation for the is_suggested field.
task.DefaultIsSuggested = taskDescIsSuggested.Default.(bool)
// taskDescCreatedAt is the schema descriptor for created_at field.
taskDescCreatedAt := taskFields[17].Descriptor()
taskDescCreatedAt := taskFields[18].Descriptor()
// task.DefaultCreatedAt holds the default value on creation for the created_at field.
task.DefaultCreatedAt = taskDescCreatedAt.Default.(func() time.Time)
// taskDescUpdatedAt is the schema descriptor for updated_at field.
taskDescUpdatedAt := taskFields[18].Descriptor()
taskDescUpdatedAt := taskFields[19].Descriptor()
// task.DefaultUpdatedAt holds the default value on creation for the updated_at field.
task.DefaultUpdatedAt = taskDescUpdatedAt.Default.(func() time.Time)
// task.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field.

View File

@@ -3,6 +3,7 @@
package db
import (
"encoding/json"
"fmt"
"strings"
"time"
@@ -37,6 +38,8 @@ type Task struct {
ProgramLanguage string `json:"program_language,omitempty"`
// WorkMode holds the value of the "work_mode" field.
WorkMode string `json:"work_mode,omitempty"`
// Prompt holds the value of the "prompt" field.
Prompt string `json:"prompt,omitempty"`
// Completion holds the value of the "completion" field.
Completion string `json:"completion,omitempty"`
// CodeLines holds the value of the "code_lines" field.
@@ -50,7 +53,7 @@ type Task struct {
// SourceCode holds the value of the "source_code" field.
SourceCode string `json:"source_code,omitempty"`
// CursorPosition holds the value of the "cursor_position" field.
CursorPosition int64 `json:"cursor_position,omitempty"`
CursorPosition map[string]interface{} `json:"cursor_position,omitempty"`
// UserInput holds the value of the "user_input" field.
UserInput string `json:"user_input,omitempty"`
// CreatedAt holds the value of the "created_at" field.
@@ -112,11 +115,13 @@ func (*Task) scanValues(columns []string) ([]any, error) {
values := make([]any, len(columns))
for i := range columns {
switch columns[i] {
case task.FieldCursorPosition:
values[i] = new([]byte)
case task.FieldIsAccept, task.FieldIsSuggested:
values[i] = new(sql.NullBool)
case task.FieldCodeLines, task.FieldInputTokens, task.FieldOutputTokens, task.FieldCursorPosition:
case task.FieldCodeLines, task.FieldInputTokens, task.FieldOutputTokens:
values[i] = new(sql.NullInt64)
case task.FieldTaskID, task.FieldRequestID, task.FieldModelType, task.FieldProgramLanguage, task.FieldWorkMode, task.FieldCompletion, task.FieldSourceCode, task.FieldUserInput:
case task.FieldTaskID, task.FieldRequestID, task.FieldModelType, task.FieldProgramLanguage, task.FieldWorkMode, task.FieldPrompt, task.FieldCompletion, task.FieldSourceCode, task.FieldUserInput:
values[i] = new(sql.NullString)
case task.FieldCreatedAt, task.FieldUpdatedAt:
values[i] = new(sql.NullTime)
@@ -191,6 +196,12 @@ func (t *Task) assignValues(columns []string, values []any) error {
} else if value.Valid {
t.WorkMode = value.String
}
case task.FieldPrompt:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field prompt", values[i])
} else if value.Valid {
t.Prompt = value.String
}
case task.FieldCompletion:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field completion", values[i])
@@ -228,10 +239,12 @@ func (t *Task) assignValues(columns []string, values []any) error {
t.SourceCode = value.String
}
case task.FieldCursorPosition:
if value, ok := values[i].(*sql.NullInt64); !ok {
if value, ok := values[i].(*[]byte); !ok {
return fmt.Errorf("unexpected type %T for field cursor_position", values[i])
} else if value.Valid {
t.CursorPosition = value.Int64
} else if value != nil && len(*value) > 0 {
if err := json.Unmarshal(*value, &t.CursorPosition); err != nil {
return fmt.Errorf("unmarshal field cursor_position: %w", err)
}
}
case task.FieldUserInput:
if value, ok := values[i].(*sql.NullString); !ok {
@@ -326,6 +339,9 @@ func (t *Task) String() string {
builder.WriteString("work_mode=")
builder.WriteString(t.WorkMode)
builder.WriteString(", ")
builder.WriteString("prompt=")
builder.WriteString(t.Prompt)
builder.WriteString(", ")
builder.WriteString("completion=")
builder.WriteString(t.Completion)
builder.WriteString(", ")

View File

@@ -30,6 +30,8 @@ const (
FieldProgramLanguage = "program_language"
// FieldWorkMode holds the string denoting the work_mode field in the database.
FieldWorkMode = "work_mode"
// FieldPrompt holds the string denoting the prompt field in the database.
FieldPrompt = "prompt"
// FieldCompletion holds the string denoting the completion field in the database.
FieldCompletion = "completion"
// FieldCodeLines holds the string denoting the code_lines field in the database.
@@ -92,6 +94,7 @@ var Columns = []string{
FieldIsAccept,
FieldProgramLanguage,
FieldWorkMode,
FieldPrompt,
FieldCompletion,
FieldCodeLines,
FieldInputTokens,
@@ -175,6 +178,11 @@ func ByWorkMode(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldWorkMode, opts...).ToFunc()
}
// ByPrompt orders the results by the prompt field.
func ByPrompt(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldPrompt, opts...).ToFunc()
}
// ByCompletion orders the results by the completion field.
func ByCompletion(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldCompletion, opts...).ToFunc()
@@ -205,11 +213,6 @@ func BySourceCode(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldSourceCode, opts...).ToFunc()
}
// ByCursorPosition orders the results by the cursor_position field.
func ByCursorPosition(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldCursorPosition, opts...).ToFunc()
}
// ByUserInput orders the results by the user_input field.
func ByUserInput(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldUserInput, opts...).ToFunc()

View File

@@ -98,6 +98,11 @@ func WorkMode(v string) predicate.Task {
return predicate.Task(sql.FieldEQ(FieldWorkMode, v))
}
// Prompt applies equality check predicate on the "prompt" field. It's identical to PromptEQ.
func Prompt(v string) predicate.Task {
return predicate.Task(sql.FieldEQ(FieldPrompt, v))
}
// Completion applies equality check predicate on the "completion" field. It's identical to CompletionEQ.
func Completion(v string) predicate.Task {
return predicate.Task(sql.FieldEQ(FieldCompletion, v))
@@ -128,11 +133,6 @@ func SourceCode(v string) predicate.Task {
return predicate.Task(sql.FieldEQ(FieldSourceCode, v))
}
// CursorPosition applies equality check predicate on the "cursor_position" field. It's identical to CursorPositionEQ.
func CursorPosition(v int64) predicate.Task {
return predicate.Task(sql.FieldEQ(FieldCursorPosition, v))
}
// UserInput applies equality check predicate on the "user_input" field. It's identical to UserInputEQ.
func UserInput(v string) predicate.Task {
return predicate.Task(sql.FieldEQ(FieldUserInput, v))
@@ -592,6 +592,81 @@ func WorkModeContainsFold(v string) predicate.Task {
return predicate.Task(sql.FieldContainsFold(FieldWorkMode, v))
}
// PromptEQ applies the EQ predicate on the "prompt" field.
func PromptEQ(v string) predicate.Task {
return predicate.Task(sql.FieldEQ(FieldPrompt, v))
}
// PromptNEQ applies the NEQ predicate on the "prompt" field.
func PromptNEQ(v string) predicate.Task {
return predicate.Task(sql.FieldNEQ(FieldPrompt, v))
}
// PromptIn applies the In predicate on the "prompt" field.
func PromptIn(vs ...string) predicate.Task {
return predicate.Task(sql.FieldIn(FieldPrompt, vs...))
}
// PromptNotIn applies the NotIn predicate on the "prompt" field.
func PromptNotIn(vs ...string) predicate.Task {
return predicate.Task(sql.FieldNotIn(FieldPrompt, vs...))
}
// PromptGT applies the GT predicate on the "prompt" field.
func PromptGT(v string) predicate.Task {
return predicate.Task(sql.FieldGT(FieldPrompt, v))
}
// PromptGTE applies the GTE predicate on the "prompt" field.
func PromptGTE(v string) predicate.Task {
return predicate.Task(sql.FieldGTE(FieldPrompt, v))
}
// PromptLT applies the LT predicate on the "prompt" field.
func PromptLT(v string) predicate.Task {
return predicate.Task(sql.FieldLT(FieldPrompt, v))
}
// PromptLTE applies the LTE predicate on the "prompt" field.
func PromptLTE(v string) predicate.Task {
return predicate.Task(sql.FieldLTE(FieldPrompt, v))
}
// PromptContains applies the Contains predicate on the "prompt" field.
func PromptContains(v string) predicate.Task {
return predicate.Task(sql.FieldContains(FieldPrompt, v))
}
// PromptHasPrefix applies the HasPrefix predicate on the "prompt" field.
func PromptHasPrefix(v string) predicate.Task {
return predicate.Task(sql.FieldHasPrefix(FieldPrompt, v))
}
// PromptHasSuffix applies the HasSuffix predicate on the "prompt" field.
func PromptHasSuffix(v string) predicate.Task {
return predicate.Task(sql.FieldHasSuffix(FieldPrompt, v))
}
// PromptIsNil applies the IsNil predicate on the "prompt" field.
func PromptIsNil() predicate.Task {
return predicate.Task(sql.FieldIsNull(FieldPrompt))
}
// PromptNotNil applies the NotNil predicate on the "prompt" field.
func PromptNotNil() predicate.Task {
return predicate.Task(sql.FieldNotNull(FieldPrompt))
}
// PromptEqualFold applies the EqualFold predicate on the "prompt" field.
func PromptEqualFold(v string) predicate.Task {
return predicate.Task(sql.FieldEqualFold(FieldPrompt, v))
}
// PromptContainsFold applies the ContainsFold predicate on the "prompt" field.
func PromptContainsFold(v string) predicate.Task {
return predicate.Task(sql.FieldContainsFold(FieldPrompt, v))
}
// CompletionEQ applies the EQ predicate on the "completion" field.
func CompletionEQ(v string) predicate.Task {
return predicate.Task(sql.FieldEQ(FieldCompletion, v))
@@ -902,46 +977,6 @@ func SourceCodeContainsFold(v string) predicate.Task {
return predicate.Task(sql.FieldContainsFold(FieldSourceCode, v))
}
// CursorPositionEQ applies the EQ predicate on the "cursor_position" field.
func CursorPositionEQ(v int64) predicate.Task {
return predicate.Task(sql.FieldEQ(FieldCursorPosition, v))
}
// CursorPositionNEQ applies the NEQ predicate on the "cursor_position" field.
func CursorPositionNEQ(v int64) predicate.Task {
return predicate.Task(sql.FieldNEQ(FieldCursorPosition, v))
}
// CursorPositionIn applies the In predicate on the "cursor_position" field.
func CursorPositionIn(vs ...int64) predicate.Task {
return predicate.Task(sql.FieldIn(FieldCursorPosition, vs...))
}
// CursorPositionNotIn applies the NotIn predicate on the "cursor_position" field.
func CursorPositionNotIn(vs ...int64) predicate.Task {
return predicate.Task(sql.FieldNotIn(FieldCursorPosition, vs...))
}
// CursorPositionGT applies the GT predicate on the "cursor_position" field.
func CursorPositionGT(v int64) predicate.Task {
return predicate.Task(sql.FieldGT(FieldCursorPosition, v))
}
// CursorPositionGTE applies the GTE predicate on the "cursor_position" field.
func CursorPositionGTE(v int64) predicate.Task {
return predicate.Task(sql.FieldGTE(FieldCursorPosition, v))
}
// CursorPositionLT applies the LT predicate on the "cursor_position" field.
func CursorPositionLT(v int64) predicate.Task {
return predicate.Task(sql.FieldLT(FieldCursorPosition, v))
}
// CursorPositionLTE applies the LTE predicate on the "cursor_position" field.
func CursorPositionLTE(v int64) predicate.Task {
return predicate.Task(sql.FieldLTE(FieldCursorPosition, v))
}
// CursorPositionIsNil applies the IsNil predicate on the "cursor_position" field.
func CursorPositionIsNil() predicate.Task {
return predicate.Task(sql.FieldIsNull(FieldCursorPosition))

View File

@@ -124,6 +124,20 @@ func (tc *TaskCreate) SetNillableWorkMode(s *string) *TaskCreate {
return tc
}
// SetPrompt sets the "prompt" field.
func (tc *TaskCreate) SetPrompt(s string) *TaskCreate {
tc.mutation.SetPrompt(s)
return tc
}
// SetNillablePrompt sets the "prompt" field if the given value is not nil.
func (tc *TaskCreate) SetNillablePrompt(s *string) *TaskCreate {
if s != nil {
tc.SetPrompt(*s)
}
return tc
}
// SetCompletion sets the "completion" field.
func (tc *TaskCreate) SetCompletion(s string) *TaskCreate {
tc.mutation.SetCompletion(s)
@@ -209,16 +223,8 @@ func (tc *TaskCreate) SetNillableSourceCode(s *string) *TaskCreate {
}
// SetCursorPosition sets the "cursor_position" field.
func (tc *TaskCreate) SetCursorPosition(i int64) *TaskCreate {
tc.mutation.SetCursorPosition(i)
return tc
}
// SetNillableCursorPosition sets the "cursor_position" field if the given value is not nil.
func (tc *TaskCreate) SetNillableCursorPosition(i *int64) *TaskCreate {
if i != nil {
tc.SetCursorPosition(*i)
}
func (tc *TaskCreate) SetCursorPosition(m map[string]interface{}) *TaskCreate {
tc.mutation.SetCursorPosition(m)
return tc
}
@@ -428,6 +434,10 @@ func (tc *TaskCreate) createSpec() (*Task, *sqlgraph.CreateSpec) {
_spec.SetField(task.FieldWorkMode, field.TypeString, value)
_node.WorkMode = value
}
if value, ok := tc.mutation.Prompt(); ok {
_spec.SetField(task.FieldPrompt, field.TypeString, value)
_node.Prompt = value
}
if value, ok := tc.mutation.Completion(); ok {
_spec.SetField(task.FieldCompletion, field.TypeString, value)
_node.Completion = value
@@ -453,7 +463,7 @@ func (tc *TaskCreate) createSpec() (*Task, *sqlgraph.CreateSpec) {
_node.SourceCode = value
}
if value, ok := tc.mutation.CursorPosition(); ok {
_spec.SetField(task.FieldCursorPosition, field.TypeInt64, value)
_spec.SetField(task.FieldCursorPosition, field.TypeJSON, value)
_node.CursorPosition = value
}
if value, ok := tc.mutation.UserInput(); ok {
@@ -696,6 +706,24 @@ func (u *TaskUpsert) ClearWorkMode() *TaskUpsert {
return u
}
// SetPrompt sets the "prompt" field.
func (u *TaskUpsert) SetPrompt(v string) *TaskUpsert {
u.Set(task.FieldPrompt, v)
return u
}
// UpdatePrompt sets the "prompt" field to the value that was provided on create.
func (u *TaskUpsert) UpdatePrompt() *TaskUpsert {
u.SetExcluded(task.FieldPrompt)
return u
}
// ClearPrompt clears the value of the "prompt" field.
func (u *TaskUpsert) ClearPrompt() *TaskUpsert {
u.SetNull(task.FieldPrompt)
return u
}
// SetCompletion sets the "completion" field.
func (u *TaskUpsert) SetCompletion(v string) *TaskUpsert {
u.Set(task.FieldCompletion, v)
@@ -817,7 +845,7 @@ func (u *TaskUpsert) ClearSourceCode() *TaskUpsert {
}
// SetCursorPosition sets the "cursor_position" field.
func (u *TaskUpsert) SetCursorPosition(v int64) *TaskUpsert {
func (u *TaskUpsert) SetCursorPosition(v map[string]interface{}) *TaskUpsert {
u.Set(task.FieldCursorPosition, v)
return u
}
@@ -828,12 +856,6 @@ func (u *TaskUpsert) UpdateCursorPosition() *TaskUpsert {
return u
}
// AddCursorPosition adds v to the "cursor_position" field.
func (u *TaskUpsert) AddCursorPosition(v int64) *TaskUpsert {
u.Add(task.FieldCursorPosition, v)
return u
}
// ClearCursorPosition clears the value of the "cursor_position" field.
func (u *TaskUpsert) ClearCursorPosition() *TaskUpsert {
u.SetNull(task.FieldCursorPosition)
@@ -1077,6 +1099,27 @@ func (u *TaskUpsertOne) ClearWorkMode() *TaskUpsertOne {
})
}
// SetPrompt sets the "prompt" field.
func (u *TaskUpsertOne) SetPrompt(v string) *TaskUpsertOne {
return u.Update(func(s *TaskUpsert) {
s.SetPrompt(v)
})
}
// UpdatePrompt sets the "prompt" field to the value that was provided on create.
func (u *TaskUpsertOne) UpdatePrompt() *TaskUpsertOne {
return u.Update(func(s *TaskUpsert) {
s.UpdatePrompt()
})
}
// ClearPrompt clears the value of the "prompt" field.
func (u *TaskUpsertOne) ClearPrompt() *TaskUpsertOne {
return u.Update(func(s *TaskUpsert) {
s.ClearPrompt()
})
}
// SetCompletion sets the "completion" field.
func (u *TaskUpsertOne) SetCompletion(v string) *TaskUpsertOne {
return u.Update(func(s *TaskUpsert) {
@@ -1218,19 +1261,12 @@ func (u *TaskUpsertOne) ClearSourceCode() *TaskUpsertOne {
}
// SetCursorPosition sets the "cursor_position" field.
func (u *TaskUpsertOne) SetCursorPosition(v int64) *TaskUpsertOne {
func (u *TaskUpsertOne) SetCursorPosition(v map[string]interface{}) *TaskUpsertOne {
return u.Update(func(s *TaskUpsert) {
s.SetCursorPosition(v)
})
}
// AddCursorPosition adds v to the "cursor_position" field.
func (u *TaskUpsertOne) AddCursorPosition(v int64) *TaskUpsertOne {
return u.Update(func(s *TaskUpsert) {
s.AddCursorPosition(v)
})
}
// UpdateCursorPosition sets the "cursor_position" field to the value that was provided on create.
func (u *TaskUpsertOne) UpdateCursorPosition() *TaskUpsertOne {
return u.Update(func(s *TaskUpsert) {
@@ -1656,6 +1692,27 @@ func (u *TaskUpsertBulk) ClearWorkMode() *TaskUpsertBulk {
})
}
// SetPrompt sets the "prompt" field.
func (u *TaskUpsertBulk) SetPrompt(v string) *TaskUpsertBulk {
return u.Update(func(s *TaskUpsert) {
s.SetPrompt(v)
})
}
// UpdatePrompt sets the "prompt" field to the value that was provided on create.
func (u *TaskUpsertBulk) UpdatePrompt() *TaskUpsertBulk {
return u.Update(func(s *TaskUpsert) {
s.UpdatePrompt()
})
}
// ClearPrompt clears the value of the "prompt" field.
func (u *TaskUpsertBulk) ClearPrompt() *TaskUpsertBulk {
return u.Update(func(s *TaskUpsert) {
s.ClearPrompt()
})
}
// SetCompletion sets the "completion" field.
func (u *TaskUpsertBulk) SetCompletion(v string) *TaskUpsertBulk {
return u.Update(func(s *TaskUpsert) {
@@ -1797,19 +1854,12 @@ func (u *TaskUpsertBulk) ClearSourceCode() *TaskUpsertBulk {
}
// SetCursorPosition sets the "cursor_position" field.
func (u *TaskUpsertBulk) SetCursorPosition(v int64) *TaskUpsertBulk {
func (u *TaskUpsertBulk) SetCursorPosition(v map[string]interface{}) *TaskUpsertBulk {
return u.Update(func(s *TaskUpsert) {
s.SetCursorPosition(v)
})
}
// AddCursorPosition adds v to the "cursor_position" field.
func (u *TaskUpsertBulk) AddCursorPosition(v int64) *TaskUpsertBulk {
return u.Update(func(s *TaskUpsert) {
s.AddCursorPosition(v)
})
}
// UpdateCursorPosition sets the "cursor_position" field to the value that was provided on create.
func (u *TaskUpsertBulk) UpdateCursorPosition() *TaskUpsertBulk {
return u.Update(func(s *TaskUpsert) {

View File

@@ -176,6 +176,26 @@ func (tu *TaskUpdate) ClearWorkMode() *TaskUpdate {
return tu
}
// SetPrompt sets the "prompt" field.
func (tu *TaskUpdate) SetPrompt(s string) *TaskUpdate {
tu.mutation.SetPrompt(s)
return tu
}
// SetNillablePrompt sets the "prompt" field if the given value is not nil.
func (tu *TaskUpdate) SetNillablePrompt(s *string) *TaskUpdate {
if s != nil {
tu.SetPrompt(*s)
}
return tu
}
// ClearPrompt clears the value of the "prompt" field.
func (tu *TaskUpdate) ClearPrompt() *TaskUpdate {
tu.mutation.ClearPrompt()
return tu
}
// SetCompletion sets the "completion" field.
func (tu *TaskUpdate) SetCompletion(s string) *TaskUpdate {
tu.mutation.SetCompletion(s)
@@ -312,23 +332,8 @@ func (tu *TaskUpdate) ClearSourceCode() *TaskUpdate {
}
// SetCursorPosition sets the "cursor_position" field.
func (tu *TaskUpdate) SetCursorPosition(i int64) *TaskUpdate {
tu.mutation.ResetCursorPosition()
tu.mutation.SetCursorPosition(i)
return tu
}
// SetNillableCursorPosition sets the "cursor_position" field if the given value is not nil.
func (tu *TaskUpdate) SetNillableCursorPosition(i *int64) *TaskUpdate {
if i != nil {
tu.SetCursorPosition(*i)
}
return tu
}
// AddCursorPosition adds i to the "cursor_position" field.
func (tu *TaskUpdate) AddCursorPosition(i int64) *TaskUpdate {
tu.mutation.AddCursorPosition(i)
func (tu *TaskUpdate) SetCursorPosition(m map[string]interface{}) *TaskUpdate {
tu.mutation.SetCursorPosition(m)
return tu
}
@@ -519,6 +524,12 @@ func (tu *TaskUpdate) sqlSave(ctx context.Context) (n int, err error) {
if tu.mutation.WorkModeCleared() {
_spec.ClearField(task.FieldWorkMode, field.TypeString)
}
if value, ok := tu.mutation.Prompt(); ok {
_spec.SetField(task.FieldPrompt, field.TypeString, value)
}
if tu.mutation.PromptCleared() {
_spec.ClearField(task.FieldPrompt, field.TypeString)
}
if value, ok := tu.mutation.Completion(); ok {
_spec.SetField(task.FieldCompletion, field.TypeString, value)
}
@@ -562,13 +573,10 @@ func (tu *TaskUpdate) sqlSave(ctx context.Context) (n int, err error) {
_spec.ClearField(task.FieldSourceCode, field.TypeString)
}
if value, ok := tu.mutation.CursorPosition(); ok {
_spec.SetField(task.FieldCursorPosition, field.TypeInt64, value)
}
if value, ok := tu.mutation.AddedCursorPosition(); ok {
_spec.AddField(task.FieldCursorPosition, field.TypeInt64, value)
_spec.SetField(task.FieldCursorPosition, field.TypeJSON, value)
}
if tu.mutation.CursorPositionCleared() {
_spec.ClearField(task.FieldCursorPosition, field.TypeInt64)
_spec.ClearField(task.FieldCursorPosition, field.TypeJSON)
}
if value, ok := tu.mutation.UserInput(); ok {
_spec.SetField(task.FieldUserInput, field.TypeString, value)
@@ -849,6 +857,26 @@ func (tuo *TaskUpdateOne) ClearWorkMode() *TaskUpdateOne {
return tuo
}
// SetPrompt sets the "prompt" field.
func (tuo *TaskUpdateOne) SetPrompt(s string) *TaskUpdateOne {
tuo.mutation.SetPrompt(s)
return tuo
}
// SetNillablePrompt sets the "prompt" field if the given value is not nil.
func (tuo *TaskUpdateOne) SetNillablePrompt(s *string) *TaskUpdateOne {
if s != nil {
tuo.SetPrompt(*s)
}
return tuo
}
// ClearPrompt clears the value of the "prompt" field.
func (tuo *TaskUpdateOne) ClearPrompt() *TaskUpdateOne {
tuo.mutation.ClearPrompt()
return tuo
}
// SetCompletion sets the "completion" field.
func (tuo *TaskUpdateOne) SetCompletion(s string) *TaskUpdateOne {
tuo.mutation.SetCompletion(s)
@@ -985,23 +1013,8 @@ func (tuo *TaskUpdateOne) ClearSourceCode() *TaskUpdateOne {
}
// SetCursorPosition sets the "cursor_position" field.
func (tuo *TaskUpdateOne) SetCursorPosition(i int64) *TaskUpdateOne {
tuo.mutation.ResetCursorPosition()
tuo.mutation.SetCursorPosition(i)
return tuo
}
// SetNillableCursorPosition sets the "cursor_position" field if the given value is not nil.
func (tuo *TaskUpdateOne) SetNillableCursorPosition(i *int64) *TaskUpdateOne {
if i != nil {
tuo.SetCursorPosition(*i)
}
return tuo
}
// AddCursorPosition adds i to the "cursor_position" field.
func (tuo *TaskUpdateOne) AddCursorPosition(i int64) *TaskUpdateOne {
tuo.mutation.AddCursorPosition(i)
func (tuo *TaskUpdateOne) SetCursorPosition(m map[string]interface{}) *TaskUpdateOne {
tuo.mutation.SetCursorPosition(m)
return tuo
}
@@ -1222,6 +1235,12 @@ func (tuo *TaskUpdateOne) sqlSave(ctx context.Context) (_node *Task, err error)
if tuo.mutation.WorkModeCleared() {
_spec.ClearField(task.FieldWorkMode, field.TypeString)
}
if value, ok := tuo.mutation.Prompt(); ok {
_spec.SetField(task.FieldPrompt, field.TypeString, value)
}
if tuo.mutation.PromptCleared() {
_spec.ClearField(task.FieldPrompt, field.TypeString)
}
if value, ok := tuo.mutation.Completion(); ok {
_spec.SetField(task.FieldCompletion, field.TypeString, value)
}
@@ -1265,13 +1284,10 @@ func (tuo *TaskUpdateOne) sqlSave(ctx context.Context) (_node *Task, err error)
_spec.ClearField(task.FieldSourceCode, field.TypeString)
}
if value, ok := tuo.mutation.CursorPosition(); ok {
_spec.SetField(task.FieldCursorPosition, field.TypeInt64, value)
}
if value, ok := tuo.mutation.AddedCursorPosition(); ok {
_spec.AddField(task.FieldCursorPosition, field.TypeInt64, value)
_spec.SetField(task.FieldCursorPosition, field.TypeJSON, value)
}
if tuo.mutation.CursorPositionCleared() {
_spec.ClearField(task.FieldCursorPosition, field.TypeInt64)
_spec.ClearField(task.FieldCursorPosition, field.TypeJSON)
}
if value, ok := tuo.mutation.UserInput(); ok {
_spec.SetField(task.FieldUserInput, field.TypeString, value)

View File

@@ -51,7 +51,7 @@ type ReportReq struct {
Tool string `json:"tool"` // 工具
UserInput string `json:"user_input"` // 用户输入的新文本用于reject action
SourceCode string `json:"source_code"` // 当前文件的原文用于reject action
CursorPosition int64 `json:"cursor_position"` // 光标位置用于reject action
CursorPosition map[string]any `json:"cursor_position"` // 光标位置用于reject action
}
type RecordParam struct {
@@ -70,9 +70,9 @@ type RecordParam struct {
WorkMode string
CodeLines int64
Code string
SourceCode string // 当前文件的原文
CursorPosition int64 // 光标位置
UserInput string // 用户实际输入的内容
SourceCode string // 当前文件的原文
CursorPosition map[string]any // 光标位置
UserInput string // 用户实际输入的内容
}
func (r *RecordParam) Clone() *RecordParam {

View File

@@ -31,6 +31,7 @@ type UserUsecase interface {
UpdateSetting(ctx context.Context, req *UpdateSettingReq) (*Setting, error)
OAuthSignUpOrIn(ctx context.Context, req *OAuthSignUpOrInReq) (*OAuthURLResp, error)
OAuthCallback(ctx *web.Context, req *OAuthCallbackReq) error
ExportCompletionData(ctx context.Context) (*ExportCompletionDataResp, error)
}
type UserRepo interface {
@@ -56,6 +57,7 @@ type UserRepo interface {
SignUpOrIn(ctx context.Context, platform consts.UserPlatform, req *OAuthUserInfo) (*db.User, error)
SaveAdminLoginHistory(ctx context.Context, adminID, ip string) error
SaveUserLoginHistory(ctx context.Context, userID, ip string, session *VSCodeSession) error
ExportCompletionData(ctx context.Context) ([]*CompletionData, error)
}
type ProfileUpdateReq struct {
@@ -388,3 +390,33 @@ func (s *Setting) From(e *db.Setting) *Setting {
return s
}
// CompletionData 补全数据导出结构
type CompletionData struct {
TaskID string `json:"task_id"` // 任务ID
UserID string `json:"user_id"` // 用户ID
ModelID string `json:"model_id"` // 模型ID
ModelName string `json:"model_name"` // 模型名称
RequestID string `json:"request_id"` // 请求ID
ModelType string `json:"model_type"` // 模型类型
ProgramLanguage string `json:"program_language"` // 编程语言
WorkMode string `json:"work_mode"` // 工作模式
Prompt string `json:"prompt"` // 用户输入的提示
Completion string `json:"completion"` // LLM生成的补全代码
SourceCode string `json:"source_code"` // 当前文件原文
CursorPosition map[string]any `json:"cursor_position"` // 光标位置 {"line": 10, "column": 5}
UserInput string `json:"user_input"` // 用户最终输入的内容
IsAccept bool `json:"is_accept"` // 用户是否接受补全
IsSuggested bool `json:"is_suggested"` // 是否为建议模式
CodeLines int64 `json:"code_lines"` // 代码行数
InputTokens int64 `json:"input_tokens"` // 输入token数
OutputTokens int64 `json:"output_tokens"` // 输出token数
CreatedAt int64 `json:"created_at"` // 创建时间戳
UpdatedAt int64 `json:"updated_at"` // 更新时间戳
}
// ExportCompletionDataResp 导出补全数据响应
type ExportCompletionDataResp struct {
TotalCount int64 `json:"total_count"` // 总记录数
Data []*CompletionData `json:"data"` // 补全数据列表
}

View File

@@ -37,14 +37,15 @@ func (Task) Fields() []ent.Field {
field.Bool("is_accept").Default(false),
field.String("program_language").Optional(),
field.String("work_mode").Optional(),
field.String("prompt").Optional(), // 用户输入的提示
field.String("completion").Optional(),
field.Int64("code_lines").Optional(),
field.Int64("input_tokens").Optional(),
field.Int64("output_tokens").Optional(),
field.Bool("is_suggested").Default(false),
field.String("source_code").Optional(), // 当前文件的原文
field.Int64("cursor_position").Optional(), // 光标位置
field.String("user_input").Optional(), // 用户实际输入的内容
field.String("source_code").Optional(), // 当前文件的原文
field.JSON("cursor_position", map[string]any{}).Optional(), // 光标位置 {"line": 10, "column": 5}
field.String("user_input").Optional(), // 用户实际输入的内容
field.Time("created_at").Default(time.Now),
field.Time("updated_at").Default(time.Now).UpdateDefault(time.Now),
}

View File

@@ -69,7 +69,7 @@ func (r *Recorder) handleShadow() {
var (
taskID, mode, prompt, language, tool, code, sourceCode, userInput string
cursorPosition int64
cursorPosition map[string]any
)
switch r.ctx.Model.ModelType {
@@ -96,8 +96,15 @@ func (r *Recorder) handleShadow() {
mode = req.Metadata["mode"]
language = req.Metadata["program_language"]
sourceCode = req.Metadata["source_code"]
if pos, err := strconv.ParseInt(req.Metadata["cursor_position"], 10, 64); err == nil {
cursorPosition = pos
// 解析cursor_position为JSON格式
if posStr := req.Metadata["cursor_position"]; posStr != "" {
if pos, err := strconv.ParseInt(posStr, 10, 64); err == nil {
cursorPosition = map[string]any{
"position": pos,
"line": 1, // 默认值
"column": pos,
}
}
}
userInput = req.Metadata["user_input"]

View File

@@ -100,6 +100,7 @@ func (r *ProxyRepo) Record(ctx context.Context, record *domain.RecordParam) erro
SetIsAccept(record.IsAccept).
SetModelType(record.ModelType).
SetWorkMode(record.WorkMode).
SetPrompt(record.Prompt).
SetCodeLines(record.CodeLines).
SetSourceCode(record.SourceCode).
SetCursorPosition(record.CursorPosition).
@@ -126,7 +127,10 @@ func (r *ProxyRepo) Record(ctx context.Context, record *domain.RecordParam) erro
if record.SourceCode != "" {
up.SetSourceCode(record.SourceCode)
}
if record.CursorPosition > 0 {
if record.Prompt != "" {
up.SetPrompt(record.Prompt)
}
if record.CursorPosition != nil {
up.SetCursorPosition(record.CursorPosition)
}
if record.UserInput != "" {
@@ -264,10 +268,16 @@ func (r *ProxyRepo) handleRejectCompletion(ctx context.Context, tx *db.Tx, rc *d
shouldRecord := false
// 检查光标位置是否匹配(允许小的误差)
if req.CursorPosition > 0 && rc.CursorPosition > 0 {
positionDiff := abs(req.CursorPosition - rc.CursorPosition)
if positionDiff <= 10 { // 允许10个字符的误差
shouldRecord = true
if req.CursorPosition != nil && rc.CursorPosition != nil {
// 从JSON中提取position值进行比较
reqPos, reqOk := req.CursorPosition["position"].(float64)
rcPos, rcOk := rc.CursorPosition["position"].(float64)
if reqOk && rcOk {
positionDiff := abs(int64(reqPos) - int64(rcPos))
if positionDiff <= 10 { // 允许10个字符的误差
shouldRecord = true
}
}
}

View File

@@ -83,6 +83,7 @@ func NewUserHandler(
admin.POST("/create", web.BindHandler(u.CreateAdmin))
admin.POST("/logout", web.BaseHandler(u.AdminLogout))
admin.DELETE("/delete", web.BaseHandler(u.DeleteAdmin))
admin.GET("/export-completion-data", web.BaseHandler(u.ExportCompletionData))
// user
g := w.Group("/api/v1/user")
@@ -620,3 +621,23 @@ func (h *UserHandler) UpdateProfile(ctx *web.Context, req domain.ProfileUpdateRe
func (h *UserHandler) InitAdmin() error {
return h.usecase.InitAdmin(context.Background())
}
// ExportCompletionData godoc
// @Summary 导出补全数据
// @Description 管理员导出所有补全相关数据
// @Tags admin
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Success 200 {object} domain.ExportCompletionDataResp
// @Failure 401 {object} errcode.Error
// @Failure 500 {object} errcode.Error
// @Router /api/v1/admin/export-completion-data [get]
func (h *UserHandler) ExportCompletionData(c *web.Context) error {
data, err := h.usecase.ExportCompletionData(c.Request().Context())
if err != nil {
return err
}
return c.JSON(http.StatusOK, data)
}

View File

@@ -18,6 +18,7 @@ import (
"github.com/chaitin/MonkeyCode/backend/db/adminloginhistory"
"github.com/chaitin/MonkeyCode/backend/db/apikey"
"github.com/chaitin/MonkeyCode/backend/db/invitecode"
"github.com/chaitin/MonkeyCode/backend/db/model"
"github.com/chaitin/MonkeyCode/backend/db/user"
"github.com/chaitin/MonkeyCode/backend/db/useridentity"
"github.com/chaitin/MonkeyCode/backend/db/userloginhistory"
@@ -437,3 +438,74 @@ func (r *UserRepo) SaveUserLoginHistory(ctx context.Context, userID string, ip s
return c.Exec(ctx)
}
func (r *UserRepo) ExportCompletionData(ctx context.Context) ([]*domain.CompletionData, error) {
// 查询所有任务数据
tasks, err := r.db.Task.Query().All(ctx)
if err != nil {
return nil, err
}
// 获取所有模型ID并查询模型信息
modelIDs := make([]uuid.UUID, 0)
for _, t := range tasks {
if t.ModelID != uuid.Nil {
modelIDs = append(modelIDs, t.ModelID)
}
}
models, err := r.db.Model.Query().Where(model.IDIn(modelIDs...)).All(ctx)
if err != nil {
return nil, err
}
// 创建模型ID到模型名称的映射
modelMap := make(map[uuid.UUID]string)
for _, m := range models {
modelMap[m.ID] = m.ShowName
}
var result []*domain.CompletionData
for _, t := range tasks {
// 获取模型名称
modelName := ""
if t.ModelID != uuid.Nil {
if name, exists := modelMap[t.ModelID]; exists {
modelName = name
}
}
// 处理cursor_position已经是JSON格式
var cursorPosition map[string]any
if t.CursorPosition != nil {
cursorPosition = t.CursorPosition
}
completionData := &domain.CompletionData{
TaskID: t.TaskID,
UserID: t.UserID.String(),
ModelID: t.ModelID.String(),
ModelName: modelName,
RequestID: t.RequestID,
ModelType: string(t.ModelType),
ProgramLanguage: t.ProgramLanguage,
WorkMode: t.WorkMode,
Prompt: t.Prompt,
Completion: t.Completion,
SourceCode: t.SourceCode,
CursorPosition: cursorPosition,
UserInput: t.UserInput,
IsAccept: t.IsAccept,
IsSuggested: t.IsSuggested,
CodeLines: t.CodeLines,
InputTokens: t.InputTokens,
OutputTokens: t.OutputTokens,
CreatedAt: t.CreatedAt.Unix(),
UpdatedAt: t.UpdatedAt.Unix(),
}
result = append(result, completionData)
}
return result, nil
}

View File

@@ -635,3 +635,15 @@ func (u *UserUsecase) ProfileUpdate(ctx context.Context, req *domain.ProfileUpda
}
return cvt.From(user, &domain.User{}), nil
}
func (u *UserUsecase) ExportCompletionData(ctx context.Context) (*domain.ExportCompletionDataResp, error) {
data, err := u.repo.ExportCompletionData(ctx)
if err != nil {
return nil, err
}
return &domain.ExportCompletionDataResp{
TotalCount: int64(len(data)),
Data: data,
}, nil
}

View File

@@ -0,0 +1,10 @@
-- 回滚cursor_position类型修改
ALTER TABLE tasks ALTER COLUMN cursor_position TYPE bigint USING
CASE
WHEN cursor_position IS NOT NULL AND cursor_position ? 'position' THEN
(cursor_position->>'position')::bigint
ELSE NULL
END;
-- 删除prompt字段
ALTER TABLE tasks DROP COLUMN IF EXISTS prompt;

View File

@@ -0,0 +1,10 @@
-- 添加prompt字段如果不存在
ALTER TABLE tasks ADD COLUMN IF NOT EXISTS prompt text;
-- 修改cursor_position为JSON类型如果还是bigint类型
ALTER TABLE tasks ALTER COLUMN cursor_position TYPE jsonb USING
CASE
WHEN cursor_position IS NOT NULL THEN
jsonb_build_object('position', cursor_position, 'line', 1, 'column', cursor_position)
ELSE NULL
END;