A per-DataDir background process owns ticket JSON, history, and sync so multiple TUI instances stay consistent; MCP token APIs are ready for phase 2. Co-authored-by: Cursor <cursoragent@cursor.com>
69 lines
1.7 KiB
Go
69 lines
1.7 KiB
Go
package api
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
|
|
"task/internal/project"
|
|
"task/internal/tmsync"
|
|
"task/internal/ytsync"
|
|
)
|
|
|
|
func (s *Server) handleSyncPull(w http.ResponseWriter, r *http.Request) {
|
|
s.runSync(w, r, false)
|
|
}
|
|
|
|
func (s *Server) handleSyncPush(w http.ResponseWriter, r *http.Request) {
|
|
s.runSync(w, r, true)
|
|
}
|
|
|
|
func (s *Server) runSync(w http.ResponseWriter, r *http.Request, push bool) {
|
|
var body struct {
|
|
ProjectID string `json:"projectId"`
|
|
}
|
|
if err := readJSON(r, &body); err != nil {
|
|
writeErr(w, http.StatusBadRequest, err.Error())
|
|
return
|
|
}
|
|
if body.ProjectID == "" {
|
|
writeErr(w, http.StatusBadRequest, "projectId required")
|
|
return
|
|
}
|
|
if !requireMCPProject(r, body.ProjectID) {
|
|
writeErr(w, http.StatusForbidden, "mcp token project mismatch")
|
|
return
|
|
}
|
|
meta, err := s.projects.LoadMeta(body.ProjectID)
|
|
if err != nil {
|
|
writeErr(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
var res ytsync.Result
|
|
ctx := context.Background()
|
|
switch meta.EffectiveBackend() {
|
|
case project.BackendTaskMaster:
|
|
if meta.TaskMaster == nil || !meta.TaskMaster.Configured() {
|
|
writeErr(w, http.StatusBadRequest, "taskmaster not configured")
|
|
return
|
|
}
|
|
syncer := &tmsync.Syncer{Store: s.store, TimeStore: s.timeStore}
|
|
if push {
|
|
res, err = syncer.Push(ctx, body.ProjectID, *meta.TaskMaster)
|
|
} else {
|
|
res, err = syncer.Pull(ctx, body.ProjectID, *meta.TaskMaster)
|
|
}
|
|
default:
|
|
if push {
|
|
res, err = ytsync.PushProject(ctx, s.projects, s.store, s.timeStore, body.ProjectID)
|
|
} else {
|
|
res, err = ytsync.PullProject(ctx, s.projects, s.store, s.timeStore, body.ProjectID)
|
|
}
|
|
}
|
|
if err != nil {
|
|
writeErr(w, http.StatusBadRequest, err.Error())
|
|
return
|
|
}
|
|
s.notify(body.ProjectID)
|
|
writeJSON(w, http.StatusOK, res)
|
|
}
|