First Commit
ci / go (push) Waiting to run
ci / go-db (agent) (push) Waiting to run
ci / go-db (config) (push) Waiting to run
ci / go-db (db) (push) Waiting to run
ci / go-db (evidence) (push) Waiting to run
ci / go-db (llmrec) (push) Waiting to run
ci / go-db (server) (push) Waiting to run
web / web (push) Waiting to run
docs / links (push) Canceled after 0s
detections / detections (push) Canceled after 0s
ci / go (push) Waiting to run
ci / go-db (agent) (push) Waiting to run
ci / go-db (config) (push) Waiting to run
ci / go-db (db) (push) Waiting to run
ci / go-db (evidence) (push) Waiting to run
ci / go-db (llmrec) (push) Waiting to run
ci / go-db (server) (push) Waiting to run
web / web (push) Waiting to run
docs / links (push) Canceled after 0s
detections / detections (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/Autumn-27/artex/db"
|
||||
)
|
||||
|
||||
const maxTaskAssetRequestBytes = 512 << 10
|
||||
|
||||
// 작업 자산 API 가 사용자에게 돌려주는 오류 응답 문구. 필드명(scope·asset_ids)은
|
||||
// 요청 본문 키라 원문 그대로 두고, 사람이 읽는 메시지만 한국어로 둔다.
|
||||
const (
|
||||
errTaskAssetRequestTooLarge = "요청 본문이 너무 큽니다"
|
||||
errTaskAssetScopeConflict = "scope 와 asset_ids 는 동시에 제출할 수 없습니다"
|
||||
)
|
||||
|
||||
func writeTaskAssetError(w http.ResponseWriter, err error) {
|
||||
switch {
|
||||
case errors.Is(err, db.ErrTaskAssetInvalid):
|
||||
writeErr(w, http.StatusBadRequest, err.Error())
|
||||
case errors.Is(err, db.ErrTaskAssetTaskNotFound), errors.Is(err, db.ErrTaskAssetAssetNotFound):
|
||||
writeErr(w, http.StatusNotFound, err.Error())
|
||||
default:
|
||||
writeErr(w, http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) attachTaskAssets(w http.ResponseWriter, r *http.Request) {
|
||||
task, ok := s.m.Task(r.PathValue("id"))
|
||||
if !ok {
|
||||
writeErr(w, http.StatusNotFound, "task not found")
|
||||
return
|
||||
}
|
||||
r.Body = http.MaxBytesReader(w, r.Body, maxTaskAssetRequestBytes)
|
||||
var request struct {
|
||||
AssetIDs []int64 `json:"asset_ids"`
|
||||
SourceSummary string `json:"source_summary"`
|
||||
Scope companyScopeInputs `json:"scope"`
|
||||
}
|
||||
if err := decode(r, &request); err != nil {
|
||||
var tooLarge *http.MaxBytesError
|
||||
if errors.As(err, &tooLarge) {
|
||||
writeErr(w, http.StatusRequestEntityTooLarge, errTaskAssetRequestTooLarge)
|
||||
} else {
|
||||
writeErr(w, http.StatusBadRequest, err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
request.SourceSummary = strings.TrimSpace(request.SourceSummary)
|
||||
taskID, _ := parseTaskID(task.ID)
|
||||
if request.Scope != nil && len(request.AssetIDs) > 0 {
|
||||
writeErr(w, http.StatusBadRequest, errTaskAssetScopeConflict)
|
||||
return
|
||||
}
|
||||
if request.Scope != nil {
|
||||
mutation, err := s.m.Assets().RegisterTaskAssetScopes(taskID, request.Scope)
|
||||
if err != nil {
|
||||
writeTaskAssetError(w, err)
|
||||
return
|
||||
}
|
||||
task.Notify()
|
||||
writeJSON(w, http.StatusOK, mutation)
|
||||
return
|
||||
}
|
||||
mutation, err := s.m.Assets().AttachAssetsToTask(taskID, request.AssetIDs, request.SourceSummary)
|
||||
if err != nil {
|
||||
writeTaskAssetError(w, err)
|
||||
return
|
||||
}
|
||||
task.Notify()
|
||||
writeJSON(w, http.StatusOK, mutation)
|
||||
}
|
||||
|
||||
func (s *Server) detachTaskAsset(w http.ResponseWriter, r *http.Request) {
|
||||
task, ok := s.m.Task(r.PathValue("id"))
|
||||
if !ok {
|
||||
writeErr(w, http.StatusNotFound, "task not found")
|
||||
return
|
||||
}
|
||||
assetID, ok := pathInt(r, "assetID")
|
||||
if !ok {
|
||||
writeErr(w, http.StatusBadRequest, "bad asset id")
|
||||
return
|
||||
}
|
||||
taskID, _ := parseTaskID(task.ID)
|
||||
detached, err := s.m.Assets().DetachAssetFromTask(taskID, assetID)
|
||||
if err != nil {
|
||||
writeTaskAssetError(w, err)
|
||||
return
|
||||
}
|
||||
if !detached {
|
||||
writeErr(w, http.StatusNotFound, "asset is not associated with this task")
|
||||
return
|
||||
}
|
||||
task.Notify()
|
||||
writeJSON(w, http.StatusOK, map[string]any{"detached": assetID})
|
||||
}
|
||||
|
||||
func (s *Server) taskIntentAssets(w http.ResponseWriter, r *http.Request) {
|
||||
task, ok := s.m.Task(r.PathValue("id"))
|
||||
if !ok {
|
||||
writeErr(w, http.StatusNotFound, "task not found")
|
||||
return
|
||||
}
|
||||
taskID, _ := parseTaskID(task.ID)
|
||||
assets, err := s.m.Assets().IntentAssets(taskID)
|
||||
if err != nil {
|
||||
writeTaskAssetError(w, err)
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, map[string]any{"assets": assets})
|
||||
}
|
||||
Reference in New Issue
Block a user