Added code for backend glue
This commit is contained in:
12
backend/internal/glue/branches.go
Normal file
12
backend/internal/glue/branches.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package glue
|
||||
|
||||
import (
|
||||
"context"
|
||||
"mind/internal/models"
|
||||
)
|
||||
|
||||
type ForkReq struct { ConversationID int64; Name string; HeadNodeID int64 }
|
||||
|
||||
func (g *Glue) ForkBranch(ctx context.Context, fr ForkReq) (models.Branch, error) {
|
||||
return g.repo.CreateOrGetBranch(ctx, fr.ConversationID, fr.Name, fr.HeadNodeID)
|
||||
}
|
||||
39
backend/internal/glue/completion.go
Normal file
39
backend/internal/glue/completion.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package glue
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
type CompletionReq struct {
|
||||
ConversationID int64 `json:"conversation_id"`
|
||||
BranchName string `json:"branch"`
|
||||
Prompt string `json:"prompt"`
|
||||
}
|
||||
|
||||
type CompletionResp struct {
|
||||
PromptNodeID int64 `json:"prompt_node_id"`
|
||||
AnswerNodeID int64 `json:"answer_node_id"`
|
||||
Answer string `json:"answer"`
|
||||
}
|
||||
|
||||
// For v0 we stub the answer as a simple echo with a prefix.
|
||||
func (g *Glue) AppendCompletion(ctx context.Context, req CompletionReq) (CompletionResp, error) {
|
||||
b, err := g.repo.GetBranch(ctx, req.ConversationID, req.BranchName)
|
||||
if err != nil { return CompletionResp{}, err }
|
||||
|
||||
// 1) create user prompt node
|
||||
promptID, err := g.repo.CreateNode(ctx, req.ConversationID, "user", req.Prompt)
|
||||
if err != nil { return CompletionResp{}, err }
|
||||
if err := g.repo.Link(ctx, b.HeadNodeID, promptID); err != nil { return CompletionResp{}, err }
|
||||
|
||||
// 2) create assistant answer node (stub)
|
||||
answerText := "(stub) You said: " + req.Prompt
|
||||
answerID, err := g.repo.CreateNode(ctx, req.ConversationID, "assistant", answerText)
|
||||
if err != nil { return CompletionResp{}, err }
|
||||
if err := g.repo.Link(ctx, promptID, answerID); err != nil { return CompletionResp{}, err }
|
||||
|
||||
// 3) move branch head
|
||||
if err := g.repo.MoveBranchHead(ctx, b.ID, answerID); err != nil { return CompletionResp{}, err }
|
||||
|
||||
return CompletionResp{PromptNodeID: promptID, AnswerNodeID: answerID, Answer: answerText}, nil
|
||||
}
|
||||
19
backend/internal/glue/conversations.go
Normal file
19
backend/internal/glue/conversations.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package glue
|
||||
|
||||
import (
|
||||
"context"
|
||||
"mind/internal/db"
|
||||
"mind/internal/models"
|
||||
)
|
||||
|
||||
type Glue struct { repo *db.Repo }
|
||||
|
||||
func NewGlue(r *db.Repo) *Glue { return &Glue{repo: r} }
|
||||
|
||||
func (g *Glue) CreateConversation(ctx context.Context, ownerID int64, title string) (int64, error) {
|
||||
return g.repo.CreateConversation(ctx, ownerID, title)
|
||||
}
|
||||
|
||||
func (g *Glue) ListConversations(ctx context.Context, ownerID int64) ([]models.Conversation, error) {
|
||||
return g.repo.ListConversations(ctx, ownerID)
|
||||
}
|
||||
41
backend/internal/glue/linearize.go
Normal file
41
backend/internal/glue/linearize.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package glue
|
||||
|
||||
import (
|
||||
"context"
|
||||
"mind/internal/models"
|
||||
)
|
||||
|
||||
type Linearized struct {
|
||||
Nodes []models.Node `json:"nodes"`
|
||||
Text string `json:"text"`
|
||||
}
|
||||
|
||||
func (g *Glue) LinearizeByBranch(ctx context.Context, convID int64, branchName string) (Linearized, error) {
|
||||
b, err := g.repo.GetBranch(ctx, convID, branchName)
|
||||
if err != nil { return Linearized{}, err }
|
||||
return g.linearizeFromHead(ctx, b.HeadNodeID)
|
||||
}
|
||||
|
||||
func (g *Glue) linearizeFromHead(ctx context.Context, head int64) (Linearized, error) {
|
||||
var seq []models.Node
|
||||
// Walk parents by latest-created parent until none
|
||||
curID := head
|
||||
for {
|
||||
n, err := g.repo.GetNode(ctx, curID)
|
||||
if err != nil { return Linearized{}, err }
|
||||
seq = append(seq, n)
|
||||
p, ok, err := g.repo.LatestParent(ctx, curID)
|
||||
if err != nil { return Linearized{}, err }
|
||||
if !ok { break }
|
||||
curID = p.ID
|
||||
}
|
||||
// Reverse seq to root→head, and stitch text
|
||||
for i, j := 0, len(seq)-1; i < j; i, j = i+1, j-1 { seq[i], seq[j] = seq[j], seq[i] }
|
||||
var txt string
|
||||
for _, n := range seq {
|
||||
role := "[user]"
|
||||
if n.AuthorKind == "assistant" { role = "[assistant]" }
|
||||
txt += role + "\n" + n.Content + "\n\n"
|
||||
}
|
||||
return Linearized{Nodes: seq, Text: txt}, nil
|
||||
}
|
||||
Reference in New Issue
Block a user