yao/sui/storages/agent/agent.go
Max 097fb73416 Refactor SUI Command Arguments and Enhance Default Template Handling
- Updated the `build` and `watch` commands to accept a single argument for `<sui>` and made the `<template>` argument optional, improving usability.
- Introduced a default template assignment for the `agent` SUI, ensuring a more intuitive setup for users.
- Enhanced error messages for command usage to provide clearer guidance on expected input format.
- Added new OpenAPI file to the bindata, improving the framework's capabilities for API integration.
2026-01-01 10:28:45 +08:00

228 lines
5 KiB
Go

package agent
import (
"fmt"
"path/filepath"
"strings"
jsoniter "github.com/json-iterator/go"
"github.com/yaoapp/gou/fs"
"github.com/yaoapp/kun/log"
"github.com/yaoapp/yao/sui/core"
)
// New create a new agent sui storage
func New(dsl *core.DSL) (*Agent, error) {
// Use "app" filesystem which is rooted at application source directory
appFS, err := fs.Get("app")
if err != nil {
return nil, err
}
// Set default public settings for agent
if dsl.Public == nil {
dsl.Public = &core.Public{}
}
if dsl.Public.Root == "" {
dsl.Public.Root = "/agents"
}
if dsl.Public.Host == "" {
dsl.Public.Host = "/"
}
if dsl.Public.Index == "" {
dsl.Public.Index = "/index"
}
return &Agent{
root: "/agent/template",
assistantsRoot: "/assistants",
fs: appFS,
DSL: dsl,
}, nil
}
// GetTemplates get the templates (returns single agent template)
func (agent *Agent) GetTemplates() ([]core.ITemplate, error) {
tmpl, err := agent.GetTemplate("agent")
if err != nil {
return nil, err
}
return []core.ITemplate{tmpl}, nil
}
// GetTemplate get the template
func (agent *Agent) GetTemplate(id string) (core.ITemplate, error) {
if id != "agent" {
return nil, fmt.Errorf("Agent storage only supports 'agent' template, got: %s", id)
}
// Check if /agent directory exists
if !agent.fs.IsDir(agent.root) {
return nil, fmt.Errorf("Agent template directory not found: %s", agent.root)
}
// Create agent template
tmpl := &Template{
Root: agent.root,
agent: agent,
Template: &core.Template{
ID: "agent",
Name: "Agent",
Version: 1,
Screenshots: []string{},
Themes: []core.SelectOption{},
},
}
// Load template.json if exists
configFile := filepath.Join(agent.root, "template.json")
if agent.fs.IsFile(configFile) {
configBytes, err := agent.fs.ReadFile(configFile)
if err != nil {
return nil, err
}
err = jsoniter.Unmarshal(configBytes, tmpl.Template)
if err != nil {
return nil, err
}
}
// Load __document.html
documentFile := filepath.Join(agent.root, "__document.html")
if agent.fs.IsFile(documentFile) {
documentBytes, err := agent.fs.ReadFile(documentFile)
if err != nil {
return nil, err
}
tmpl.Document = documentBytes
}
// Load __data.json
dataFile := filepath.Join(agent.root, "__data.json")
if agent.fs.IsFile(dataFile) {
dataBytes, err := agent.fs.ReadFile(dataFile)
if err != nil {
return nil, err
}
tmpl.GlobalData = dataBytes
}
// Load build script
err := tmpl.loadBuildScript()
if err != nil {
log.Warn("[Agent] Failed to load build script: %v", err)
}
return tmpl, nil
}
// UploadTemplate upload the template (not supported for agent)
func (agent *Agent) UploadTemplate(src string, dst string) (core.ITemplate, error) {
return nil, fmt.Errorf("UploadTemplate is not supported for agent storage")
}
// PublicRootMatcher get the public root matcher
func (agent *Agent) PublicRootMatcher() *core.Matcher {
return &core.Matcher{Exact: agent.DSL.Public.Root}
}
// Setting get the setting
func (agent *Agent) Setting() (*core.Setting, error) {
return &core.Setting{
ID: agent.DSL.ID,
Guard: agent.DSL.Guard,
Option: map[string]interface{}{
"disableCodeEditor": true,
},
}, nil
}
// PublicRoot get the public root
func (agent *Agent) PublicRoot(data map[string]interface{}) (string, error) {
return agent.DSL.Public.Root, nil
}
// WithSid set the session id
func (agent *Agent) WithSid(sid string) {
agent.DSL.Sid = sid
}
// getAssistants get all assistant directories that have pages
func (agent *Agent) getAssistants() ([]string, error) {
if !agent.fs.IsDir(agent.assistantsRoot) {
return []string{}, nil
}
dirs, err := agent.fs.ReadDir(agent.assistantsRoot, false)
if err != nil {
return nil, err
}
assistants := []string{}
for _, dir := range dirs {
if !agent.fs.IsDir(dir) {
continue
}
// Check if this assistant has a pages directory
pagesDir := filepath.Join(dir, "pages")
if agent.fs.IsDir(pagesDir) {
name := filepath.Base(dir)
assistants = append(assistants, name)
}
}
return assistants, nil
}
// getAssistantPagesRoot get the pages root for an assistant
func (agent *Agent) getAssistantPagesRoot(assistantID string) string {
return filepath.Join(agent.assistantsRoot, assistantID, "pages")
}
// Exists check if the agent storage is available
func Exists() bool {
appFS, err := fs.Get("app")
if err != nil {
return false
}
return appFS.IsDir("/agent/template")
}
// HasAssistantPages check if any assistant has pages
func HasAssistantPages() bool {
appFS, err := fs.Get("app")
if err != nil {
return false
}
if !appFS.IsDir("/assistants") {
return false
}
dirs, err := appFS.ReadDir("/assistants", false)
if err != nil {
return false
}
for _, dir := range dirs {
if !appFS.IsDir(dir) {
continue
}
pagesDir := filepath.Join(dir, "pages")
if appFS.IsDir(pagesDir) {
return true
}
}
return false
}
// log helper
func init() {
_ = log.Debug
_ = strings.TrimPrefix
}