Files
codex-bot d6ee8942f1
Foundry Go checks / check (push) Successful in 2m40s
Foundry Go checks / check (pull_request) Successful in 2m36s
Implement Canvas V2 subgraphs, assets and asynchronous AI execution
2026-11-06 18:36:00 +08:00

93 lines
2.4 KiB
Go

package platform
import (
"context"
"encoding/json"
"net/http"
"time"
"gitea.entroia.com/Zayden-Jung/foundry-core/internal/codex"
)
func (s *service) canvasAIModels(w http.ResponseWriter, r *http.Request, project, account string) error {
if r.Method != http.MethodGet {
reject(w, 405, "method_not_allowed")
return nil
}
tx, err := s.db.BeginTx(r.Context(), nil)
if err != nil {
return err
}
defer tx.Rollback()
kind, _, err := lockMaterial(r.Context(), tx, project, r.PathValue("workspace"), r.PathValue("material"), account)
if err != nil {
return err
}
if kind != "board" {
reject(w, 400, "invalid_material")
return nil
}
ctx, cancel := context.WithTimeout(r.Context(), 5*time.Second)
defer cancel()
models, err := s.canvasAI.Models(ctx)
if err != nil {
reply(w, 200, response{"models": []any{}, "unavailable_reason": "codex_unavailable"})
return nil
}
imageAvailable := false
for _, model := range models {
if model.Available && canvasModelSupports(model, "image") {
imageAvailable = true
}
}
capability := response{"available": imageAvailable}
if !imageAvailable {
capability["unavailable_reason"] = "worker_has_no_verified_image_output"
}
reply(w, 200, response{"models": models, "image_generation": capability})
return nil
}
func (s *service) validateCanvasAIModels(w http.ResponseWriter, r *http.Request, raw json.RawMessage) bool {
data := canvasNodeData(raw)
configured := []map[string]any{}
for _, d := range data {
if ai, ok := d["ai"].(map[string]any); ok {
configured = append(configured, ai)
}
}
if len(configured) == 0 {
return true
}
ctx, cancel := context.WithTimeout(r.Context(), 5*time.Second)
defer cancel()
models, err := s.canvasAI.Models(ctx)
if err != nil {
reject(w, 503, "codex_unavailable")
return false
}
catalogue := map[string]codex.CanvasModel{}
for _, model := range models {
catalogue[model.ID] = model
}
for _, ai := range configured {
params, _ := ai["parameters"].(map[string]any)
if len(params) > 0 {
reject(w, 400, "invalid_ai_request")
return false
}
id, _ := ai["modelId"].(string)
if id == "" && ai["enabled"] != true {
continue
}
model, exists := catalogue[id]
if !exists || !model.Available {
reject(w, 422, "model_unavailable")
return false
}
// The verified CLI catalog currently exposes an empty parameter schema.
// Arbitrary CLI arguments and unknown model-specific keys are rejected.
}
return true
}