diff --git a/apiclient/types/agent.go b/apiclient/types/agent.go index 7e3bca47b..bc7f14a10 100644 --- a/apiclient/types/agent.go +++ b/apiclient/types/agent.go @@ -11,8 +11,9 @@ import ( type Agent struct { Metadata AgentManifest - AliasAssigned bool `json:"aliasAssigned,omitempty"` - AuthStatus map[string]OAuthAppLoginAuthStatus `json:"authStatus,omitempty"` + AliasAssigned bool `json:"aliasAssigned,omitempty"` + AuthStatus map[string]OAuthAppLoginAuthStatus `json:"authStatus,omitempty"` + TextEmbeddingModel string `json:"textEmbeddingModel,omitempty"` } type AgentList List[Agent] diff --git a/apiclient/types/defaultmodelalias.go b/apiclient/types/defaultmodelalias.go new file mode 100644 index 000000000..ae509e205 --- /dev/null +++ b/apiclient/types/defaultmodelalias.go @@ -0,0 +1,21 @@ +package types + +type DefaultModelAliasType string + +const ( + DefaultModelAliasTypeTextEmbedding DefaultModelAliasType = "text-embedding" + DefaultModelAliasTypeLLM DefaultModelAliasType = "llm" + DefaultModelAliasTypeLLMMini DefaultModelAliasType = "llm-mini" + DefaultModelAliasTypeImageGeneration DefaultModelAliasType = "image-generation" +) + +type DefaultModelAlias struct { + DefaultModelAliasManifest +} + +type DefaultModelAliasManifest struct { + Alias string `json:"alias"` + Model string `json:"model"` +} + +type DefaultModelAliasList List[DefaultModelAlias] diff --git a/apiclient/types/model.go b/apiclient/types/model.go index 5b1d9530a..d2d6ba4cd 100644 --- a/apiclient/types/model.go +++ b/apiclient/types/model.go @@ -12,7 +12,6 @@ type ModelManifest struct { ModelProvider string `json:"modelProvider,omitempty"` Alias string `json:"alias,omitempty"` Active bool `json:"active"` - Default bool `json:"default"` Usage ModelUsage `json:"usage,omitempty"` } @@ -31,7 +30,7 @@ type ModelProviderStatus struct { type ModelUsage string const ( - ModelUsageAgent ModelUsage = "agent" + ModelUsageLLM ModelUsage = "llm" ModelUsageEmbedding ModelUsage = "text-embedding" ModelUsageImage ModelUsage = "image-generation" ) diff --git a/apiclient/types/workflow.go b/apiclient/types/workflow.go index 5a08acc76..64b104ddb 100644 --- a/apiclient/types/workflow.go +++ b/apiclient/types/workflow.go @@ -5,8 +5,9 @@ import "strings" type Workflow struct { Metadata WorkflowManifest - AliasAssigned bool `json:"aliasAssigned,omitempty"` - AuthStatus map[string]OAuthAppLoginAuthStatus `json:"authStatus,omitempty"` + AliasAssigned bool `json:"aliasAssigned,omitempty"` + AuthStatus map[string]OAuthAppLoginAuthStatus `json:"authStatus,omitempty"` + TextEmbeddingModel string `json:"textEmbeddingModel,omitempty"` } type WorkflowList List[Workflow] diff --git a/apiclient/types/zz_generated.deepcopy.go b/apiclient/types/zz_generated.deepcopy.go index 4e1d33681..e6c496f37 100644 --- a/apiclient/types/zz_generated.deepcopy.go +++ b/apiclient/types/zz_generated.deepcopy.go @@ -322,6 +322,57 @@ func (in *CronJobManifest) DeepCopy() *CronJobManifest { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DefaultModelAlias) DeepCopyInto(out *DefaultModelAlias) { + *out = *in + out.DefaultModelAliasManifest = in.DefaultModelAliasManifest +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DefaultModelAlias. +func (in *DefaultModelAlias) DeepCopy() *DefaultModelAlias { + if in == nil { + return nil + } + out := new(DefaultModelAlias) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DefaultModelAliasList) DeepCopyInto(out *DefaultModelAliasList) { + *out = *in + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]DefaultModelAlias, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DefaultModelAliasList. +func (in *DefaultModelAliasList) DeepCopy() *DefaultModelAliasList { + if in == nil { + return nil + } + out := new(DefaultModelAliasList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DefaultModelAliasManifest) DeepCopyInto(out *DefaultModelAliasManifest) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DefaultModelAliasManifest. +func (in *DefaultModelAliasManifest) DeepCopy() *DefaultModelAliasManifest { + if in == nil { + return nil + } + out := new(DefaultModelAliasManifest) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *EmailReceiver) DeepCopyInto(out *EmailReceiver) { *out = *in @@ -1126,6 +1177,116 @@ func (in *SubFlow) DeepCopy() *SubFlow { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Task) DeepCopyInto(out *Task) { + *out = *in + in.Metadata.DeepCopyInto(&out.Metadata) + in.TaskManifest.DeepCopyInto(&out.TaskManifest) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Task. +func (in *Task) DeepCopy() *Task { + if in == nil { + return nil + } + out := new(Task) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TaskIf) DeepCopyInto(out *TaskIf) { + *out = *in + if in.Steps != nil { + in, out := &in.Steps, &out.Steps + *out = make([]TaskStep, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Else != nil { + in, out := &in.Else, &out.Else + *out = make([]TaskStep, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TaskIf. +func (in *TaskIf) DeepCopy() *TaskIf { + if in == nil { + return nil + } + out := new(TaskIf) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TaskList) DeepCopyInto(out *TaskList) { + *out = *in + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Task, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TaskList. +func (in *TaskList) DeepCopy() *TaskList { + if in == nil { + return nil + } + out := new(TaskList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TaskManifest) DeepCopyInto(out *TaskManifest) { + *out = *in + if in.Steps != nil { + in, out := &in.Steps, &out.Steps + *out = make([]TaskStep, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TaskManifest. +func (in *TaskManifest) DeepCopy() *TaskManifest { + if in == nil { + return nil + } + out := new(TaskManifest) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TaskStep) DeepCopyInto(out *TaskStep) { + *out = *in + if in.If != nil { + in, out := &in.If, &out.If + *out = new(TaskIf) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TaskStep. +func (in *TaskStep) DeepCopy() *TaskStep { + if in == nil { + return nil + } + out := new(TaskStep) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Template) DeepCopyInto(out *Template) { *out = *in diff --git a/pkg/alias/get.go b/pkg/alias/get.go index a9404e1ff..8e0c56791 100644 --- a/pkg/alias/get.go +++ b/pkg/alias/get.go @@ -53,6 +53,44 @@ func Get(ctx context.Context, c kclient.Client, obj v1.Aliasable, namespace stri return c.Get(ctx, router.Key(alias.Spec.TargetNamespace, alias.Spec.TargetName), obj.(kclient.Object)) } +func GetFromScope(ctx context.Context, c kclient.Client, scope, namespace, name string) (kclient.Object, error) { + gvk := schema.GroupVersionKind{ + Group: v1.SchemeGroupVersion.Group, + Version: v1.Version, + Kind: scope, + } + + obj, err := c.Scheme().New(gvk) + if err != nil { + return nil, apierrors.NewNotFound(schema.GroupResource{ + Group: gvk.Group, + Resource: gvk.Kind, + }, name) + } + + cObj := obj.(kclient.Object) + + var alias v1.Alias + if err := c.Get(ctx, router.Key("", KeyFromScopeID(scope, name)), &alias); apierrors.IsNotFound(err) { + return cObj, c.Get(ctx, router.Key(namespace, name), cObj) + } else if err != nil { + return nil, err + } + + gvk.Kind = alias.Spec.TargetKind + obj, err = c.Scheme().New(gvk) + if err != nil { + return nil, apierrors.NewNotFound(schema.GroupResource{ + Group: gvk.Group, + Resource: gvk.Kind, + }, name) + } + + cObj = obj.(kclient.Object) + + return cObj, c.Get(ctx, router.Key(alias.Spec.TargetNamespace, alias.Spec.TargetName), cObj) +} + func KeyFromScopeID(scope, id string) string { return system.AliasPrefix + hash.String(name.SafeHashConcatName(id, scope))[:8] } diff --git a/pkg/api/handlers/agent.go b/pkg/api/handlers/agent.go index 29394654b..4309b0ab1 100644 --- a/pkg/api/handlers/agent.go +++ b/pkg/api/handlers/agent.go @@ -54,17 +54,17 @@ func (a *AgentHandler) Update(req api.Context) error { return err } - return req.Write(convertAgent(agent, server.GetURLPrefix(req))) + resp, err := convertAgent(agent, req) + if err != nil { + return err + } + return req.WriteCreated(resp) } func (a *AgentHandler) Delete(req api.Context) error { - var ( - id = req.PathValue("id") - ) - return req.Delete(&v1.Agent{ ObjectMeta: metav1.ObjectMeta{ - Name: id, + Name: req.PathValue("id"), Namespace: req.Namespace(), }, }) @@ -89,12 +89,16 @@ func (a *AgentHandler) Create(req api.Context) error { return err } - return req.WriteCreated(convertAgent(agent, server.GetURLPrefix(req))) + resp, err := convertAgent(agent, req) + if err != nil { + return err + } + return req.WriteCreated(resp) } -func convertAgent(agent v1.Agent, prefix string) *types.Agent { +func convertAgent(agent v1.Agent, req api.Context) (*types.Agent, error) { var links []string - if prefix != "" { + if prefix := server.GetURLPrefix(req); prefix != "" { alias := agent.Name if agent.Status.AliasAssigned && agent.Spec.Manifest.Alias != "" { alias = agent.Spec.Manifest.Alias @@ -102,12 +106,22 @@ func convertAgent(agent v1.Agent, prefix string) *types.Agent { links = []string{"invoke", prefix + "/invoke/" + alias} } - return &types.Agent{ - Metadata: MetadataFrom(&agent, links...), - AgentManifest: agent.Spec.Manifest, - AliasAssigned: agent.Status.AliasAssigned, - AuthStatus: agent.Status.AuthStatus, + var embeddingModel string + if len(agent.Status.KnowledgeSetNames) > 0 { + var ks v1.KnowledgeSet + if err := req.Get(&ks, agent.Status.KnowledgeSetNames[0]); err != nil { + return nil, fmt.Errorf("failed to get KnowledgeSet %q: %v", agent.Status.KnowledgeSetNames[0], err) + } + embeddingModel = ks.Status.TextEmbeddingModel } + + return &types.Agent{ + Metadata: MetadataFrom(&agent, links...), + AgentManifest: agent.Spec.Manifest, + AliasAssigned: agent.Status.AliasAssigned, + AuthStatus: agent.Status.AuthStatus, + TextEmbeddingModel: embeddingModel, + }, nil } func (a *AgentHandler) ByID(req api.Context) error { @@ -115,7 +129,12 @@ func (a *AgentHandler) ByID(req api.Context) error { if err := alias.Get(req.Context(), req.Storage, &agent, req.Namespace(), req.PathValue("id")); err != nil { return err } - return req.Write(convertAgent(agent, server.GetURLPrefix(req))) + + resp, err := convertAgent(agent, req) + if err != nil { + return err + } + return req.WriteCreated(resp) } func (a *AgentHandler) List(req api.Context) error { @@ -126,7 +145,11 @@ func (a *AgentHandler) List(req api.Context) error { var resp types.AgentList for _, agent := range agentList.Items { - resp.Items = append(resp.Items, *convertAgent(agent, server.GetURLPrefix(req))) + convertedAgent, err := convertAgent(agent, req) + if err != nil { + return err + } + resp.Items = append(resp.Items, *convertedAgent) } return req.Write(resp) @@ -503,12 +526,20 @@ func (a *AgentHandler) EnsureCredentialForKnowledgeSource(req api.Context) error // If auth is not required, then don't continue. if authStatus.Required != nil && !*authStatus.Required { - return req.Write(convertAgent(agent, server.GetURLPrefix(req))) + resp, err := convertAgent(agent, req) + if err != nil { + return err + } + return req.WriteCreated(resp) } // if auth is already authenticated, then don't continue. if authStatus.Authenticated { - return req.Write(convertAgent(agent, server.GetURLPrefix(req))) + resp, err := convertAgent(agent, req) + if err != nil { + return err + } + return req.WriteCreated(resp) } credentialTool, err := v1.CredentialTool(req.Context(), req.Storage, req.Namespace(), ref) @@ -524,7 +555,11 @@ func (a *AgentHandler) EnsureCredentialForKnowledgeSource(req api.Context) error authStatus.Required = &[]bool{false}[0] agent.Status.AuthStatus[ref] = authStatus - return req.Write(convertAgent(agent, server.GetURLPrefix(req))) + resp, err := convertAgent(agent, req) + if err != nil { + return err + } + return req.WriteCreated(resp) } oauthLogin := &v1.OAuthAppLogin{ @@ -558,7 +593,11 @@ func (a *AgentHandler) EnsureCredentialForKnowledgeSource(req api.Context) error } agent.Status.AuthStatus[ref] = oauthLogin.Status.External - return req.Write(convertAgent(agent, server.GetURLPrefix(req))) + resp, err := convertAgent(agent, req) + if err != nil { + return err + } + return req.WriteCreated(resp) } func (a *AgentHandler) Script(req api.Context) error { diff --git a/pkg/api/handlers/defaultmodelalias.go b/pkg/api/handlers/defaultmodelalias.go new file mode 100644 index 000000000..85c508df9 --- /dev/null +++ b/pkg/api/handlers/defaultmodelalias.go @@ -0,0 +1,93 @@ +package handlers + +import ( + "github.com/otto8-ai/otto8/apiclient/types" + "github.com/otto8-ai/otto8/pkg/api" + v1 "github.com/otto8-ai/otto8/pkg/storage/apis/otto.otto8.ai/v1" + "github.com/otto8-ai/otto8/pkg/system" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +type DefaultModelAliasHandler struct{} + +func NewDefaultModelAliasHandler() *DefaultModelAliasHandler { + return &DefaultModelAliasHandler{} +} + +func (d *DefaultModelAliasHandler) Create(req api.Context) error { + var manifest types.DefaultModelAliasManifest + if err := req.Read(&manifest); err != nil { + return err + } + + dma := v1.DefaultModelAlias{ + ObjectMeta: metav1.ObjectMeta{ + GenerateName: system.DefaultModelAliasPrefix, + Namespace: req.Namespace(), + }, + Spec: v1.DefaultModelAliasSpec{ + Manifest: manifest, + }, + } + + if err := req.Create(&dma); err != nil { + return err + } + + return req.WriteCreated(convertDefaultModelAlias(dma)) +} + +func (d *DefaultModelAliasHandler) GetByID(req api.Context) error { + var dma v1.DefaultModelAlias + if err := req.Get(&dma, req.PathValue("id")); err != nil { + return err + } + return req.Write(convertDefaultModelAlias(dma)) +} + +func (d *DefaultModelAliasHandler) List(req api.Context) error { + var dmaList v1.DefaultModelAliasList + if err := req.List(&dmaList); err != nil { + return err + } + + resp := make([]types.DefaultModelAlias, 0, len(dmaList.Items)) + for _, dma := range dmaList.Items { + resp = append(resp, convertDefaultModelAlias(dma)) + } + return req.Write(types.DefaultModelAliasList{Items: resp}) +} + +func (d *DefaultModelAliasHandler) Update(req api.Context) error { + var dma v1.DefaultModelAlias + if err := req.Get(&dma, req.PathValue("id")); err != nil { + return err + } + + var manifest types.DefaultModelAliasManifest + if err := req.Read(&manifest); err != nil { + return err + } + + dma.Spec.Manifest = manifest + if err := req.Update(&dma); err != nil { + return err + } + + return req.WriteCreated(convertDefaultModelAlias(dma)) +} + +func (d *DefaultModelAliasHandler) Delete(req api.Context) error { + return req.Delete(&v1.DefaultModelAlias{ + ObjectMeta: metav1.ObjectMeta{ + Name: req.PathValue("id"), + Namespace: req.Namespace(), + }, + }) +} + +func convertDefaultModelAlias(d v1.DefaultModelAlias) types.DefaultModelAlias { + return types.DefaultModelAlias{ + DefaultModelAliasManifest: d.Spec.Manifest, + } +} diff --git a/pkg/api/handlers/model.go b/pkg/api/handlers/model.go index d8e3e6d67..761fc1ba6 100644 --- a/pkg/api/handlers/model.go +++ b/pkg/api/handlers/model.go @@ -70,7 +70,7 @@ func (a *ModelHandler) Update(req api.Context) error { existing.Spec.Manifest = model - if err := validateModelManifestAndSetDefaults(req.Context(), req.Storage, &existing); err != nil { + if err := validateModelManifestAndSetDefaults(&existing); err != nil { return err } @@ -115,7 +115,7 @@ func (a *ModelHandler) Create(req api.Context) error { }, } - if err := validateModelManifestAndSetDefaults(req.Context(), req.Storage, &model); err != nil { + if err := validateModelManifestAndSetDefaults(&model); err != nil { return err } @@ -187,7 +187,7 @@ func convertModelProviderToolRef(toolRef v1.ToolReference) *types.ModelProviderS } } -func validateModelManifestAndSetDefaults(ctx context.Context, c kclient.Client, newModel *v1.Model) error { +func validateModelManifestAndSetDefaults(newModel *v1.Model) error { var errs []error if newModel.Spec.Manifest.TargetModel == "" { errs = append(errs, fmt.Errorf("field targetModel is required")) @@ -197,21 +197,7 @@ func validateModelManifestAndSetDefaults(ctx context.Context, c kclient.Client, } if newModel.Spec.Manifest.Usage == "" { - newModel.Spec.Manifest.Usage = types.ModelUsageAgent - } - - if newModel.Spec.Manifest.Default && newModel.Spec.Manifest.Active { - // Ensure only one default model exists - var modelList v1.ModelList - if err := c.List(ctx, &modelList); err != nil { - return err - } - - for _, model := range modelList.Items { - if model.Spec.Manifest.Default && model.Spec.Manifest.Active && model.Name != newModel.Name { - return types.NewErrBadRequest("model %s is already the default model", model.Name) - } - } + newModel.Spec.Manifest.Usage = types.ModelUsageLLM } return errors.Join(errs...) diff --git a/pkg/api/handlers/workflows.go b/pkg/api/handlers/workflows.go index 63bdc8d60..6c24de7fe 100644 --- a/pkg/api/handlers/workflows.go +++ b/pkg/api/handlers/workflows.go @@ -87,7 +87,12 @@ func (a *WorkflowHandler) Update(req api.Context) error { return err } - return req.Write(convertWorkflow(wf, server.GetURLPrefix(req))) + resp, err := convertWorkflow(wf, req) + if err != nil { + return err + } + + return req.WriteCreated(resp) } func (a *WorkflowHandler) Delete(req api.Context) error { @@ -123,24 +128,40 @@ func (a *WorkflowHandler) Create(req api.Context) error { return err } - return req.WriteCreated(convertWorkflow(workflow, server.GetURLPrefix(req))) + resp, err := convertWorkflow(workflow, req) + if err != nil { + return err + } + + return req.WriteCreated(resp) } -func convertWorkflow(workflow v1.Workflow, prefix string) *types.Workflow { +func convertWorkflow(workflow v1.Workflow, req api.Context) (*types.Workflow, error) { var links []string - if prefix != "" { + if prefix := server.GetURLPrefix(req); prefix != "" { alias := workflow.Name if workflow.Status.AliasAssigned && workflow.Spec.Manifest.Alias != "" { alias = workflow.Spec.Manifest.Alias } links = []string{"invoke", prefix + "/invoke/" + alias} } - return &types.Workflow{ - Metadata: MetadataFrom(&workflow, links...), - WorkflowManifest: workflow.Spec.Manifest, - AliasAssigned: workflow.Status.AliasAssigned, - AuthStatus: workflow.Status.AuthStatus, + + var embeddingModel string + if len(workflow.Status.KnowledgeSetNames) > 0 { + var ks v1.KnowledgeSet + if err := req.Get(&ks, workflow.Status.KnowledgeSetNames[0]); err != nil { + return nil, fmt.Errorf("failed to get KnowledgeSet %q: %v", workflow.Status.KnowledgeSetNames[0], err) + } + embeddingModel = ks.Status.TextEmbeddingModel } + + return &types.Workflow{ + Metadata: MetadataFrom(&workflow, links...), + WorkflowManifest: workflow.Spec.Manifest, + AliasAssigned: workflow.Status.AliasAssigned, + AuthStatus: workflow.Status.AuthStatus, + TextEmbeddingModel: embeddingModel, + }, nil } func (a *WorkflowHandler) ByID(req api.Context) error { @@ -153,7 +174,12 @@ func (a *WorkflowHandler) ByID(req api.Context) error { return err } - return req.Write(convertWorkflow(workflow, server.GetURLPrefix(req))) + resp, err := convertWorkflow(workflow, req) + if err != nil { + return err + } + + return req.WriteCreated(resp) } func (a *WorkflowHandler) List(req api.Context) error { @@ -164,7 +190,12 @@ func (a *WorkflowHandler) List(req api.Context) error { var resp types.WorkflowList for _, workflow := range workflowList.Items { - resp.Items = append(resp.Items, *convertWorkflow(workflow, server.GetURLPrefix(req))) + convertedWorkflow, err := convertWorkflow(workflow, req) + if err != nil { + return err + } + + resp.Items = append(resp.Items, *convertedWorkflow) } return req.Write(resp) @@ -181,12 +212,22 @@ func (a *WorkflowHandler) EnsureCredentialForKnowledgeSource(req api.Context) er // If auth is not required, then don't continue. if authStatus.Required != nil && !*authStatus.Required { - return req.Write(convertWorkflow(wf, server.GetURLPrefix(req))) + resp, err := convertWorkflow(wf, req) + if err != nil { + return err + } + + return req.WriteCreated(resp) } // if auth is already authenticated, then don't continue. if authStatus.Authenticated { - return req.Write(convertWorkflow(wf, server.GetURLPrefix(req))) + resp, err := convertWorkflow(wf, req) + if err != nil { + return err + } + + return req.WriteCreated(resp) } credentialTool, err := v1.CredentialTool(req.Context(), req.Storage, req.Namespace(), ref) @@ -202,7 +243,12 @@ func (a *WorkflowHandler) EnsureCredentialForKnowledgeSource(req api.Context) er authStatus.Required = &[]bool{false}[0] wf.Status.AuthStatus[ref] = authStatus - return req.Write(convertWorkflow(wf, server.GetURLPrefix(req))) + resp, err := convertWorkflow(wf, req) + if err != nil { + return err + } + + return req.WriteCreated(resp) } oauthLogin := &v1.OAuthAppLogin{ @@ -236,7 +282,12 @@ func (a *WorkflowHandler) EnsureCredentialForKnowledgeSource(req api.Context) er } wf.Status.AuthStatus[ref] = oauthLogin.Status.External - return req.Write(convertWorkflow(wf, server.GetURLPrefix(req))) + resp, err := convertWorkflow(wf, req) + if err != nil { + return err + } + + return req.WriteCreated(resp) } func (a *WorkflowHandler) Script(req api.Context) error { diff --git a/pkg/api/router/router.go b/pkg/api/router/router.go index c5812f2e3..371b9a76b 100644 --- a/pkg/api/router/router.go +++ b/pkg/api/router/router.go @@ -24,6 +24,7 @@ func Router(services *services.Services) (http.Handler, error) { models := handlers.NewModelHandler() prompt := handlers.NewPromptHandler(services.GPTClient) emailreceiver := handlers.NewEmailReceiverHandler(services.EmailServerName) + defaultModelAliases := handlers.NewDefaultModelAliasHandler() // Version mux.HandleFunc("GET /api/version", handlers.GetVersion) @@ -217,6 +218,13 @@ func Router(services *services.Services) (http.Handler, error) { mux.HandleFunc("GET /api/models", models.List) mux.HandleFunc("GET /api/models/{id}", models.ByID) + // Default Model Aliases + mux.HandleFunc("GET /api/default-model-aliases", defaultModelAliases.List) + mux.HandleFunc("GET /api/default-model-aliases/{id}", defaultModelAliases.GetByID) + mux.HandleFunc("POST /api/default-model-aliases", defaultModelAliases.Create) + mux.HandleFunc("PUT /api/default-model-aliases/{id}", defaultModelAliases.Update) + mux.HandleFunc("DELETE /api/default-model-aliases/{id}", defaultModelAliases.Delete) + // Prompt mux.HandleFunc("POST /api/prompt", prompt.Prompt) diff --git a/pkg/controller/data/data.go b/pkg/controller/data/data.go index 0ae598fea..6fbc57793 100644 --- a/pkg/controller/data/data.go +++ b/pkg/controller/data/data.go @@ -17,6 +17,9 @@ var ottoData []byte //go:embed default-models.yaml var defaultModelsData []byte +//go:embed default-model-aliases.yaml +var defaultModelAliasesData []byte + func Data(ctx context.Context, c kclient.Client) error { var defaultModels v1.ModelList if err := yaml.Unmarshal(defaultModelsData, &defaultModels); err != nil { @@ -42,6 +45,22 @@ func Data(ctx context.Context, c kclient.Client) error { } } + var defaultModelAliases v1.DefaultModelAliasList + if err := yaml.Unmarshal(defaultModelAliasesData, &defaultModelAliases); err != nil { + return err + } + + for _, alias := range defaultModelAliases.Items { + var existing v1.DefaultModelAlias + if err := c.Get(ctx, kclient.ObjectKey{Namespace: alias.Namespace, Name: alias.Name}, &existing); apierrors.IsNotFound(err) { + if err := c.Create(ctx, &alias); err != nil { + return err + } + } else if err != nil { + return err + } + } + var otto v1.Agent if err := yaml.Unmarshal(ottoData, &otto); err != nil { return err diff --git a/pkg/controller/data/default-model-aliases.yaml b/pkg/controller/data/default-model-aliases.yaml new file mode 100644 index 000000000..2df678916 --- /dev/null +++ b/pkg/controller/data/default-model-aliases.yaml @@ -0,0 +1,37 @@ +items: + - apiVersion: otto.otto8.ai/v1 + kind: DefaultModelAlias + metadata: + name: llm + namespace: default + spec: + manifest: + alias: llm + model: gpt-4o + - apiVersion: otto.otto8.ai/v1 + kind: DefaultModelAlias + metadata: + name: llm-mini + namespace: default + spec: + manifest: + alias: llm-mini + model: gpt-4o-mini + - apiVersion: otto.otto8.ai/v1 + kind: DefaultModelAlias + metadata: + name: text-embedding + namespace: default + spec: + manifest: + alias: text-embedding + model: text-embedding-3-small + - apiVersion: otto.otto8.ai/v1 + kind: DefaultModelAlias + metadata: + name: image-generation + namespace: default + spec: + manifest: + alias: image-generation + model: dall-e-3 \ No newline at end of file diff --git a/pkg/controller/data/default-models.yaml b/pkg/controller/data/default-models.yaml index 2ce80a347..26da4bd27 100644 --- a/pkg/controller/data/default-models.yaml +++ b/pkg/controller/data/default-models.yaml @@ -8,9 +8,8 @@ items: manifest: targetModel: gpt-4o modelProvider: openai-model-provider - default: true active: true - usage: agent + usage: llm - apiVersion: otto.otto8.ai/v1 kind: Model metadata: @@ -54,7 +53,7 @@ items: targetModel: gpt-4o-mini modelProvider: openai-model-provider active: true - usage: agent + usage: llm - apiVersion: otto.otto8.ai/v1 kind: Model metadata: @@ -65,4 +64,4 @@ items: targetModel: gpt-3.5-turbo modelProvider: openai-model-provider active: true - usage: agent + usage: llm diff --git a/pkg/controller/handlers/alias/alias.go b/pkg/controller/handlers/alias/alias.go index 68a5f349e..7f82b815e 100644 --- a/pkg/controller/handlers/alias/alias.go +++ b/pkg/controller/handlers/alias/alias.go @@ -55,7 +55,6 @@ func AssignAlias(req router.Request, _ router.Response) error { TargetNamespace: req.Object.GetNamespace(), TargetKind: gvk.Kind, }, - Status: v1.EmptyStatus{}, } if err := create.IfNotExists(req.Ctx, req.Client, alias); err != nil { return err diff --git a/pkg/controller/handlers/knowledgefile/knowledgefile.go b/pkg/controller/handlers/knowledgefile/knowledgefile.go index c6d6da844..ae2fab400 100644 --- a/pkg/controller/handlers/knowledgefile/knowledgefile.go +++ b/pkg/controller/handlers/knowledgefile/knowledgefile.go @@ -81,6 +81,11 @@ func (h *Handler) IngestFile(req router.Request, _ router.Response) error { return kclient.IgnoreNotFound(err) } + if ks.Status.TextEmbeddingModel == "" { + // Wait for the embedding model to be set + return nil + } + thread, err := getThread(req.Ctx, req.Client, &ks, &source) if err != nil { return err @@ -255,6 +260,8 @@ func (h *Handler) ingest(ctx context.Context, client kclient.Client, file *v1.Kn "workspaceID": thread.Status.WorkspaceID, "workspaceFileName": outputFile(file.Spec.FileName), }, + }, invoke.SystemTaskOptions{ + Env: []string{"OPENAI_EMBEDDING_MODEL=" + ks.Status.TextEmbeddingModel}, }) if err != nil { return fmt.Errorf("failed to invoke ingestion task, error: %w", err) diff --git a/pkg/controller/handlers/knowledgeset/knowledgeset.go b/pkg/controller/handlers/knowledgeset/knowledgeset.go index 1e13a83db..e97ff926c 100644 --- a/pkg/controller/handlers/knowledgeset/knowledgeset.go +++ b/pkg/controller/handlers/knowledgeset/knowledgeset.go @@ -7,6 +7,7 @@ import ( "github.com/otto8-ai/nah/pkg/name" "github.com/otto8-ai/nah/pkg/router" + "github.com/otto8-ai/otto8/apiclient/types" "github.com/otto8-ai/otto8/pkg/aihelper" "github.com/otto8-ai/otto8/pkg/create" "github.com/otto8-ai/otto8/pkg/invoke" @@ -105,13 +106,62 @@ func (h *Handler) createThread(ctx context.Context, c kclient.Client, ks *v1.Kno func (h *Handler) CheckHasContent(req router.Request, _ router.Response) error { ks := req.Object.(*v1.KnowledgeSet) - files := &v1.KnowledgeFileList{} - if err := req.Client.List(req.Ctx, files, kclient.InNamespace(ks.Namespace), kclient.MatchingFields{ + + // This is a hack to track exactly when the knowledge set has no more content. + // The issue is triggers. Triggers on field or label selectors work fine, but not for deleted objects. + // When an object is deleted, there is no way to tell if it matches the field selector because the object is gone. + // Therefore, field and label selector triggers don't trigger on deletion. + // However, it is important that we clean up the dataset when the knowledge set is empty. + // So, we track a single file because this will be triggered when the file is deleted. Once the last file is deleted, then the knowledge set is empty, + // and we can clean up the dataset. + if ks.Status.ExistingFile != "" { + var file v1.KnowledgeFile + if err := req.Get(&file, req.Namespace, ks.Status.ExistingFile); err == nil { + return nil + } else if !apierrors.IsNotFound(err) { + return err + } + } + + var files v1.KnowledgeFileList + if err := req.Client.List(req.Ctx, &files, kclient.InNamespace(ks.Namespace), kclient.MatchingFields{ "spec.knowledgeSetName": ks.Name, - }, kclient.Limit(1)); err != nil { + }); err != nil { return err } + ks.Status.HasContent = len(files.Items) > 0 + if !ks.Status.HasContent { + // Reset the embedding model so it can be implicitly updated when knowledge is added. + ks.Status.TextEmbeddingModel = "" + ks.Status.ExistingFile = "" + } else { + ks.Status.ExistingFile = files.Items[0].Name + } + + return nil +} + +func (h *Handler) SetEmbeddingModel(req router.Request, _ router.Response) error { + ks := req.Object.(*v1.KnowledgeSet) + if !ks.Status.HasContent || ks.Status.TextEmbeddingModel != "" { + return nil + } + + if ks.Spec.TextEmbeddingModel != "" { + ks.Status.TextEmbeddingModel = ks.Spec.TextEmbeddingModel + return nil + } + + var defaultEmbeddingModel v1.DefaultModelAlias + if err := req.Get(&defaultEmbeddingModel, req.Namespace, string(types.DefaultModelAliasTypeTextEmbedding)); err == nil { + ks.Status.TextEmbeddingModel = defaultEmbeddingModel.Spec.Manifest.Model + } else if apierrors.IsNotFound(err) { + ks.Status.TextEmbeddingModel = "text-embedding-3-small" + } else if err != nil { + return err + } + return nil } @@ -127,7 +177,7 @@ func (h *Handler) CreateWorkspace(req router.Request, _ router.Response) error { func (h *Handler) Cleanup(req router.Request, _ router.Response) error { ks := req.Object.(*v1.KnowledgeSet) - if ks.Status.ThreadName == "" { + if ks.Status.ThreadName == "" || (ks.DeletionTimestamp.IsZero() && ks.Status.HasContent) { return nil } @@ -138,9 +188,7 @@ func (h *Handler) Cleanup(req router.Request, _ router.Response) error { return err } - task, err := h.invoker.SystemTask(req.Ctx, &thread, system.KnowledgeDeleteTool, map[string]any{ - "dataset": ks.Namespace + "/" + ks.Name, - }) + task, err := h.invoker.SystemTask(req.Ctx, &thread, system.KnowledgeDeleteTool, ks.Namespace+"/"+ks.Name) if err != nil { return err } diff --git a/pkg/controller/handlers/threads/threads.go b/pkg/controller/handlers/threads/threads.go index 3604f2793..56d310344 100644 --- a/pkg/controller/handlers/threads/threads.go +++ b/pkg/controller/handlers/threads/threads.go @@ -87,13 +87,23 @@ func CreateKnowledgeSet(req router.Request, _ router.Response) error { Finalizers: []string{v1.KnowledgeSetFinalizer}, }, Spec: v1.KnowledgeSetSpec{ - ThreadName: thread.Name, + ThreadName: thread.Name, + TextEmbeddingModel: thread.Spec.TextEmbeddingModel, }, } + if err := create.OrGet(req.Ctx, req.Client, ws); err != nil { return err } + if ws.Spec.TextEmbeddingModel != thread.Spec.TextEmbeddingModel { + // The thread knowledge set must have the same text embedding model as its agent. + ws.Spec.TextEmbeddingModel = thread.Spec.TextEmbeddingModel + if err := req.Client.Update(req.Ctx, ws); err != nil { + return err + } + } + thread.Status.KnowledgeSetNames = append(thread.Status.KnowledgeSetNames, ws.Name) return req.Client.Status().Update(req.Ctx, thread) } diff --git a/pkg/controller/routes.go b/pkg/controller/routes.go index 0ecc84713..c6bf8607c 100644 --- a/pkg/controller/routes.go +++ b/pkg/controller/routes.go @@ -74,6 +74,7 @@ func (c *Controller) setupRoutes() error { root.Type(&v1.Agent{}).HandlerFunc(alias.AssignAlias) root.Type(&v1.Workflow{}).HandlerFunc(alias.AssignAlias) root.Type(&v1.Model{}).HandlerFunc(alias.AssignAlias) + root.Type(&v1.DefaultModelAlias{}).HandlerFunc(alias.AssignAlias) // Knowledge files root.Type(&v1.KnowledgeFile{}).HandlerFunc(cleanup.Cleanup) @@ -89,9 +90,13 @@ func (c *Controller) setupRoutes() error { // KnowledgeSets root.Type(&v1.KnowledgeSet{}).HandlerFunc(cleanup.Cleanup) root.Type(&v1.KnowledgeSet{}).FinalizeFunc(v1.KnowledgeSetFinalizer, knowledgeset.Cleanup) + // Also cleanup the dataset when there is no content. + // This will allow the user to switch the embedding model implicitly. + root.Type(&v1.KnowledgeSet{}).HandlerFunc(knowledgeset.Cleanup) root.Type(&v1.KnowledgeSet{}).HandlerFunc(knowledgeset.GenerateDataDescription) root.Type(&v1.KnowledgeSet{}).HandlerFunc(knowledgeset.CreateWorkspace) root.Type(&v1.KnowledgeSet{}).HandlerFunc(knowledgeset.CheckHasContent) + root.Type(&v1.KnowledgeSet{}).HandlerFunc(knowledgeset.SetEmbeddingModel) // Webhooks root.Type(&v1.Webhook{}).HandlerFunc(cleanup.Cleanup) diff --git a/pkg/gateway/server/dispatcher/dispatcher.go b/pkg/gateway/server/dispatcher/dispatcher.go index d3dbcc6a7..41e9291a8 100644 --- a/pkg/gateway/server/dispatcher/dispatcher.go +++ b/pkg/gateway/server/dispatcher/dispatcher.go @@ -82,12 +82,23 @@ func (d *Dispatcher) TransformRequest(req *http.Request, namespace string) error } func (d *Dispatcher) getModelProviderForModel(ctx context.Context, namespace, model string) (*v1.Model, error) { - var m v1.Model - if err := alias.Get(ctx, d.client, &m, namespace, model); err != nil { + m, err := alias.GetFromScope(ctx, d.client, "Model", namespace, model) + if err != nil { return nil, err } - return &m, nil + switch m := m.(type) { + case *v1.DefaultModelAlias: + var model v1.Model + if err := alias.Get(ctx, d.client, &model, namespace, m.Spec.Manifest.Model); err != nil { + return nil, err + } + return &model, nil + case *v1.Model: + return m, nil + } + + return nil, fmt.Errorf("model %q not found", model) } func (d *Dispatcher) startModelProvider(ctx context.Context, model *v1.Model) (*url.URL, error) { diff --git a/pkg/invoke/invoker.go b/pkg/invoke/invoker.go index 102ca52ab..1b519ec42 100644 --- a/pkg/invoke/invoker.go +++ b/pkg/invoke/invoker.go @@ -200,7 +200,7 @@ func CreateThreadForAgent(ctx context.Context, c kclient.WithWatch, agent *v1.Ag if agent.Name != "" { agent, err = wait.For(ctx, c, agent, func(agent *v1.Agent) bool { - return agent.Status.WorkspaceName != "" + return agent.Status.WorkspaceName != "" && len(agent.Status.KnowledgeSetNames) > 0 }) if err != nil { return nil, err @@ -208,6 +208,11 @@ func CreateThreadForAgent(ctx context.Context, c kclient.WithWatch, agent *v1.Ag fromWorkspaceNames = []string{agent.Status.WorkspaceName} } + var agentKnowledgeSet v1.KnowledgeSet + if err = c.Get(ctx, router.Key(agent.Namespace, agent.Status.KnowledgeSetNames[0]), &agentKnowledgeSet); err != nil { + return nil, err + } + thread := v1.Thread{ ObjectMeta: metav1.ObjectMeta{ GenerateName: system.ThreadPrefix, @@ -222,6 +227,7 @@ func CreateThreadForAgent(ctx context.Context, c kclient.WithWatch, agent *v1.Ag FromWorkspaceNames: fromWorkspaceNames, UserUID: userUID, AgentAlias: agentAlias, + TextEmbeddingModel: agentKnowledgeSet.Spec.TextEmbeddingModel, }, } return &thread, c.Create(ctx, &thread) diff --git a/pkg/storage/apis/otto.otto8.ai/v1/defaultmodelalias.go b/pkg/storage/apis/otto.otto8.ai/v1/defaultmodelalias.go new file mode 100644 index 000000000..1ea151037 --- /dev/null +++ b/pkg/storage/apis/otto.otto8.ai/v1/defaultmodelalias.go @@ -0,0 +1,46 @@ +package v1 + +import ( + "github.com/otto8-ai/otto8/apiclient/types" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +type DefaultModelAlias struct { + v1.TypeMeta `json:",inline"` + v1.ObjectMeta `json:"metadata,omitempty"` + + Spec DefaultModelAliasSpec `json:"spec"` + Status DefaultModelAliasStatus `json:"status"` +} + +func (a *DefaultModelAlias) IsAssigned() bool { + return true +} + +func (a *DefaultModelAlias) GetAliasName() string { + return a.Spec.Manifest.Alias +} + +func (a *DefaultModelAlias) SetAssigned(bool) {} + +func (a *DefaultModelAlias) GetAliasScope() string { + return "Model" +} + +type DefaultModelAliasSpec struct { + Manifest types.DefaultModelAliasManifest `json:"manifest"` +} + +type DefaultModelAliasStatus struct { + SetAliasName string `json:"setAliasName"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +type DefaultModelAliasList struct { + v1.TypeMeta `json:",inline"` + v1.ListMeta `json:"metadata,omitempty"` + Items []DefaultModelAlias `json:"items"` +} diff --git a/pkg/storage/apis/otto.otto8.ai/v1/knowledgeset.go b/pkg/storage/apis/otto.otto8.ai/v1/knowledgeset.go index a994d9a3b..d3a742c80 100644 --- a/pkg/storage/apis/otto.otto8.ai/v1/knowledgeset.go +++ b/pkg/storage/apis/otto.otto8.ai/v1/knowledgeset.go @@ -23,6 +23,8 @@ type KnowledgeSetSpec struct { WorkflowName string `json:"workflowName,omitempty"` // ThreadName is the name of the thread that created and owns this knowledge set ThreadName string `json:"threadName,omitempty"` + // TextEmbeddingModel is set when the model is predetermined on creation. For example, agent threads. + TextEmbeddingModel string `json:"textEmbeddingModel,omitempty"` } func (in *KnowledgeSet) GetColumns() [][]string { @@ -73,6 +75,8 @@ type KnowledgeSetStatus struct { SuggestedDataDescription string `json:"suggestedDataDescription,omitempty"` WorkspaceName string `json:"workspaceName,omitempty"` ThreadName string `json:"threadName,omitempty"` + ExistingFile string `json:"existingFile,omitempty"` + TextEmbeddingModel string `json:"textEmbeddingModel,omitempty"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/pkg/storage/apis/otto.otto8.ai/v1/model.go b/pkg/storage/apis/otto.otto8.ai/v1/model.go index db262a2f3..89847c6e7 100644 --- a/pkg/storage/apis/otto.otto8.ai/v1/model.go +++ b/pkg/storage/apis/otto.otto8.ai/v1/model.go @@ -1,17 +1,10 @@ package v1 import ( - "fmt" - - "github.com/otto8-ai/nah/pkg/fields" "github.com/otto8-ai/otto8/apiclient/types" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -var ( - _ fields.Fields = (*Model)(nil) -) - // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object type Model struct { @@ -33,25 +26,6 @@ func (m *Model) SetAssigned(assigned bool) { m.Status.AliasAssigned = assigned } -func (m *Model) Has(field string) bool { - return m.Get(field) != "" -} - -func (m *Model) Get(field string) string { - if m != nil { - switch field { - case "spec.manifest.default": - return fmt.Sprintf("%v", m.Spec.Manifest.Default) - } - } - - return "" -} - -func (m *Model) FieldNames() []string { - return []string{"spec.manifest.default"} -} - type ModelSpec struct { Manifest types.ModelManifest `json:"manifest,omitempty"` } diff --git a/pkg/storage/apis/otto.otto8.ai/v1/run.go b/pkg/storage/apis/otto.otto8.ai/v1/run.go index 3dc313744..5437142f8 100644 --- a/pkg/storage/apis/otto.otto8.ai/v1/run.go +++ b/pkg/storage/apis/otto.otto8.ai/v1/run.go @@ -7,11 +7,12 @@ import ( ) const ( - RunFinalizer = "otto.otto8.ai/run" - KnowledgeFileFinalizer = "otto.otto8.ai/knowledge-file" - WorkspaceFinalizer = "otto.otto8.ai/workspace" - KnowledgeSetFinalizer = "otto.otto8.ai/knowledge-set" - KnowledgeSourceFinalizer = "otto.otto8.ai/knowledge-source" + RunFinalizer = "otto.otto8.ai/run" + KnowledgeFileFinalizer = "otto.otto8.ai/knowledge-file" + WorkspaceFinalizer = "otto.otto8.ai/workspace" + KnowledgeSetFinalizer = "otto.otto8.ai/knowledge-set" + KnowledgeSourceFinalizer = "otto.otto8.ai/knowledge-source" + DefaultModelAliasFinalizer = "otto.otto8.ai/default-model-alias" ) // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/pkg/storage/apis/otto.otto8.ai/v1/scheme.go b/pkg/storage/apis/otto.otto8.ai/v1/scheme.go index c31d16c08..5bc7b5775 100644 --- a/pkg/storage/apis/otto.otto8.ai/v1/scheme.go +++ b/pkg/storage/apis/otto.otto8.ai/v1/scheme.go @@ -59,6 +59,8 @@ func AddToSchemeWithGV(scheme *runtime.Scheme, schemeGroupVersion schema.GroupVe &OAuthAppLoginList{}, &Model{}, &ModelList{}, + &DefaultModelAlias{}, + &DefaultModelAliasList{}, ); err != nil { return err } diff --git a/pkg/storage/apis/otto.otto8.ai/v1/thread.go b/pkg/storage/apis/otto.otto8.ai/v1/thread.go index c85e05905..d7220b089 100644 --- a/pkg/storage/apis/otto.otto8.ai/v1/thread.go +++ b/pkg/storage/apis/otto.otto8.ai/v1/thread.go @@ -63,6 +63,7 @@ type ThreadSpec struct { FromWorkspaceNames []string `json:"fromWorkspaceNames,omitempty"` OAuthAppLoginName string `json:"oAuthAppLoginName,omitempty"` UserUID string `json:"userUID,omitempty"` + TextEmbeddingModel string `json:"textEmbeddingModel,omitempty"` SystemTask bool `json:"systemTask,omitempty"` } diff --git a/pkg/storage/apis/otto.otto8.ai/v1/zz_generated.deepcopy.go b/pkg/storage/apis/otto.otto8.ai/v1/zz_generated.deepcopy.go index 43bb0ac6c..88c31d86e 100644 --- a/pkg/storage/apis/otto.otto8.ai/v1/zz_generated.deepcopy.go +++ b/pkg/storage/apis/otto.otto8.ai/v1/zz_generated.deepcopy.go @@ -299,6 +299,96 @@ func (in *CronJobStatus) DeepCopy() *CronJobStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DefaultModelAlias) DeepCopyInto(out *DefaultModelAlias) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DefaultModelAlias. +func (in *DefaultModelAlias) DeepCopy() *DefaultModelAlias { + if in == nil { + return nil + } + out := new(DefaultModelAlias) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *DefaultModelAlias) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DefaultModelAliasList) DeepCopyInto(out *DefaultModelAliasList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]DefaultModelAlias, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DefaultModelAliasList. +func (in *DefaultModelAliasList) DeepCopy() *DefaultModelAliasList { + if in == nil { + return nil + } + out := new(DefaultModelAliasList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *DefaultModelAliasList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DefaultModelAliasSpec) DeepCopyInto(out *DefaultModelAliasSpec) { + *out = *in + out.Manifest = in.Manifest +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DefaultModelAliasSpec. +func (in *DefaultModelAliasSpec) DeepCopy() *DefaultModelAliasSpec { + if in == nil { + return nil + } + out := new(DefaultModelAliasSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DefaultModelAliasStatus) DeepCopyInto(out *DefaultModelAliasStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DefaultModelAliasStatus. +func (in *DefaultModelAliasStatus) DeepCopy() *DefaultModelAliasStatus { + if in == nil { + return nil + } + out := new(DefaultModelAliasStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *EmailReceiver) DeepCopyInto(out *EmailReceiver) { *out = *in diff --git a/pkg/storage/openapi/generated/openapi_generated.go b/pkg/storage/openapi/generated/openapi_generated.go index f146ee664..c7c348ed1 100644 --- a/pkg/storage/openapi/generated/openapi_generated.go +++ b/pkg/storage/openapi/generated/openapi_generated.go @@ -29,6 +29,9 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/otto8-ai/otto8/apiclient/types.CronJob": schema_otto8_ai_otto8_apiclient_types_CronJob(ref), "github.com/otto8-ai/otto8/apiclient/types.CronJobList": schema_otto8_ai_otto8_apiclient_types_CronJobList(ref), "github.com/otto8-ai/otto8/apiclient/types.CronJobManifest": schema_otto8_ai_otto8_apiclient_types_CronJobManifest(ref), + "github.com/otto8-ai/otto8/apiclient/types.DefaultModelAlias": schema_otto8_ai_otto8_apiclient_types_DefaultModelAlias(ref), + "github.com/otto8-ai/otto8/apiclient/types.DefaultModelAliasList": schema_otto8_ai_otto8_apiclient_types_DefaultModelAliasList(ref), + "github.com/otto8-ai/otto8/apiclient/types.DefaultModelAliasManifest": schema_otto8_ai_otto8_apiclient_types_DefaultModelAliasManifest(ref), "github.com/otto8-ai/otto8/apiclient/types.EmailReceiver": schema_otto8_ai_otto8_apiclient_types_EmailReceiver(ref), "github.com/otto8-ai/otto8/apiclient/types.EmailReceiverList": schema_otto8_ai_otto8_apiclient_types_EmailReceiverList(ref), "github.com/otto8-ai/otto8/apiclient/types.EmailReceiverManifest": schema_otto8_ai_otto8_apiclient_types_EmailReceiverManifest(ref), @@ -63,6 +66,11 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/otto8-ai/otto8/apiclient/types.Step": schema_otto8_ai_otto8_apiclient_types_Step(ref), "github.com/otto8-ai/otto8/apiclient/types.StepTemplateInvoke": schema_otto8_ai_otto8_apiclient_types_StepTemplateInvoke(ref), "github.com/otto8-ai/otto8/apiclient/types.SubFlow": schema_otto8_ai_otto8_apiclient_types_SubFlow(ref), + "github.com/otto8-ai/otto8/apiclient/types.Task": schema_otto8_ai_otto8_apiclient_types_Task(ref), + "github.com/otto8-ai/otto8/apiclient/types.TaskIf": schema_otto8_ai_otto8_apiclient_types_TaskIf(ref), + "github.com/otto8-ai/otto8/apiclient/types.TaskList": schema_otto8_ai_otto8_apiclient_types_TaskList(ref), + "github.com/otto8-ai/otto8/apiclient/types.TaskManifest": schema_otto8_ai_otto8_apiclient_types_TaskManifest(ref), + "github.com/otto8-ai/otto8/apiclient/types.TaskStep": schema_otto8_ai_otto8_apiclient_types_TaskStep(ref), "github.com/otto8-ai/otto8/apiclient/types.Template": schema_otto8_ai_otto8_apiclient_types_Template(ref), "github.com/otto8-ai/otto8/apiclient/types.Thread": schema_otto8_ai_otto8_apiclient_types_Thread(ref), "github.com/otto8-ai/otto8/apiclient/types.ThreadList": schema_otto8_ai_otto8_apiclient_types_ThreadList(ref), @@ -96,6 +104,10 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/otto8-ai/otto8/pkg/storage/apis/otto.otto8.ai/v1.CronJobList": schema_storage_apis_ottootto8ai_v1_CronJobList(ref), "github.com/otto8-ai/otto8/pkg/storage/apis/otto.otto8.ai/v1.CronJobSpec": schema_storage_apis_ottootto8ai_v1_CronJobSpec(ref), "github.com/otto8-ai/otto8/pkg/storage/apis/otto.otto8.ai/v1.CronJobStatus": schema_storage_apis_ottootto8ai_v1_CronJobStatus(ref), + "github.com/otto8-ai/otto8/pkg/storage/apis/otto.otto8.ai/v1.DefaultModelAlias": schema_storage_apis_ottootto8ai_v1_DefaultModelAlias(ref), + "github.com/otto8-ai/otto8/pkg/storage/apis/otto.otto8.ai/v1.DefaultModelAliasList": schema_storage_apis_ottootto8ai_v1_DefaultModelAliasList(ref), + "github.com/otto8-ai/otto8/pkg/storage/apis/otto.otto8.ai/v1.DefaultModelAliasSpec": schema_storage_apis_ottootto8ai_v1_DefaultModelAliasSpec(ref), + "github.com/otto8-ai/otto8/pkg/storage/apis/otto.otto8.ai/v1.DefaultModelAliasStatus": schema_storage_apis_ottootto8ai_v1_DefaultModelAliasStatus(ref), "github.com/otto8-ai/otto8/pkg/storage/apis/otto.otto8.ai/v1.EmailReceiver": schema_storage_apis_ottootto8ai_v1_EmailReceiver(ref), "github.com/otto8-ai/otto8/pkg/storage/apis/otto.otto8.ai/v1.EmailReceiverList": schema_storage_apis_ottootto8ai_v1_EmailReceiverList(ref), "github.com/otto8-ai/otto8/pkg/storage/apis/otto.otto8.ai/v1.EmailReceiverSpec": schema_storage_apis_ottootto8ai_v1_EmailReceiverSpec(ref), @@ -263,6 +275,12 @@ func schema_otto8_ai_otto8_apiclient_types_Agent(ref common.ReferenceCallback) c }, }, }, + "textEmbeddingModel": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, }, Required: []string{"Metadata", "AgentManifest"}, }, @@ -861,6 +879,82 @@ func schema_otto8_ai_otto8_apiclient_types_CronJobManifest(ref common.ReferenceC } } +func schema_otto8_ai_otto8_apiclient_types_DefaultModelAlias(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "DefaultModelAliasManifest": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/otto8-ai/otto8/apiclient/types.DefaultModelAliasManifest"), + }, + }, + }, + Required: []string{"DefaultModelAliasManifest"}, + }, + }, + Dependencies: []string{ + "github.com/otto8-ai/otto8/apiclient/types.DefaultModelAliasManifest"}, + } +} + +func schema_otto8_ai_otto8_apiclient_types_DefaultModelAliasList(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "items": { + SchemaProps: spec.SchemaProps{ + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/otto8-ai/otto8/apiclient/types.DefaultModelAlias"), + }, + }, + }, + }, + }, + }, + Required: []string{"items"}, + }, + }, + Dependencies: []string{ + "github.com/otto8-ai/otto8/apiclient/types.DefaultModelAlias"}, + } +} + +func schema_otto8_ai_otto8_apiclient_types_DefaultModelAliasManifest(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "alias": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "model": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"alias", "model"}, + }, + }, + } +} + func schema_otto8_ai_otto8_apiclient_types_EmailReceiver(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -1614,13 +1708,6 @@ func schema_otto8_ai_otto8_apiclient_types_ModelManifest(ref common.ReferenceCal Format: "", }, }, - "default": { - SchemaProps: spec.SchemaProps{ - Default: false, - Type: []string{"boolean"}, - Format: "", - }, - }, "usage": { SchemaProps: spec.SchemaProps{ Type: []string{"string"}, @@ -1628,7 +1715,7 @@ func schema_otto8_ai_otto8_apiclient_types_ModelManifest(ref common.ReferenceCal }, }, }, - Required: []string{"active", "default"}, + Required: []string{"active"}, }, }, } @@ -2440,6 +2527,180 @@ func schema_otto8_ai_otto8_apiclient_types_SubFlow(ref common.ReferenceCallback) } } +func schema_otto8_ai_otto8_apiclient_types_Task(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "Metadata": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/otto8-ai/otto8/apiclient/types.Metadata"), + }, + }, + "TaskManifest": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/otto8-ai/otto8/apiclient/types.TaskManifest"), + }, + }, + }, + Required: []string{"Metadata", "TaskManifest"}, + }, + }, + Dependencies: []string{ + "github.com/otto8-ai/otto8/apiclient/types.Metadata", "github.com/otto8-ai/otto8/apiclient/types.TaskManifest"}, + } +} + +func schema_otto8_ai_otto8_apiclient_types_TaskIf(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "condition": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + "steps": { + SchemaProps: spec.SchemaProps{ + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/otto8-ai/otto8/apiclient/types.TaskStep"), + }, + }, + }, + }, + }, + "else": { + SchemaProps: spec.SchemaProps{ + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/otto8-ai/otto8/apiclient/types.TaskStep"), + }, + }, + }, + }, + }, + }, + }, + }, + Dependencies: []string{ + "github.com/otto8-ai/otto8/apiclient/types.TaskStep"}, + } +} + +func schema_otto8_ai_otto8_apiclient_types_TaskList(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "items": { + SchemaProps: spec.SchemaProps{ + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/otto8-ai/otto8/apiclient/types.Task"), + }, + }, + }, + }, + }, + }, + Required: []string{"items"}, + }, + }, + Dependencies: []string{ + "github.com/otto8-ai/otto8/apiclient/types.Task"}, + } +} + +func schema_otto8_ai_otto8_apiclient_types_TaskManifest(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "name": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "description": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "steps": { + SchemaProps: spec.SchemaProps{ + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/otto8-ai/otto8/apiclient/types.TaskStep"), + }, + }, + }, + }, + }, + }, + Required: []string{"name", "description", "steps"}, + }, + }, + Dependencies: []string{ + "github.com/otto8-ai/otto8/apiclient/types.TaskStep"}, + } +} + +func schema_otto8_ai_otto8_apiclient_types_TaskStep(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "id": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + "if": { + SchemaProps: spec.SchemaProps{ + Ref: ref("github.com/otto8-ai/otto8/apiclient/types.TaskIf"), + }, + }, + "step": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + Dependencies: []string{ + "github.com/otto8-ai/otto8/apiclient/types.TaskIf"}, + } +} + func schema_otto8_ai_otto8_apiclient_types_Template(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -3176,6 +3437,12 @@ func schema_otto8_ai_otto8_apiclient_types_Workflow(ref common.ReferenceCallback }, }, }, + "textEmbeddingModel": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, }, Required: []string{"Metadata", "WorkflowManifest"}, }, @@ -4016,6 +4283,142 @@ func schema_storage_apis_ottootto8ai_v1_CronJobStatus(ref common.ReferenceCallba } } +func schema_storage_apis_ottootto8ai_v1_DefaultModelAlias(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + Type: []string{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + Type: []string{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"), + }, + }, + "spec": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/otto8-ai/otto8/pkg/storage/apis/otto.otto8.ai/v1.DefaultModelAliasSpec"), + }, + }, + "status": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/otto8-ai/otto8/pkg/storage/apis/otto.otto8.ai/v1.DefaultModelAliasStatus"), + }, + }, + }, + Required: []string{"spec", "status"}, + }, + }, + Dependencies: []string{ + "github.com/otto8-ai/otto8/pkg/storage/apis/otto.otto8.ai/v1.DefaultModelAliasSpec", "github.com/otto8-ai/otto8/pkg/storage/apis/otto.otto8.ai/v1.DefaultModelAliasStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, + } +} + +func schema_storage_apis_ottootto8ai_v1_DefaultModelAliasList(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + Type: []string{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + Type: []string{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"), + }, + }, + "items": { + SchemaProps: spec.SchemaProps{ + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/otto8-ai/otto8/pkg/storage/apis/otto.otto8.ai/v1.DefaultModelAlias"), + }, + }, + }, + }, + }, + }, + Required: []string{"items"}, + }, + }, + Dependencies: []string{ + "github.com/otto8-ai/otto8/pkg/storage/apis/otto.otto8.ai/v1.DefaultModelAlias", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, + } +} + +func schema_storage_apis_ottootto8ai_v1_DefaultModelAliasSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "manifest": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/otto8-ai/otto8/apiclient/types.DefaultModelAliasManifest"), + }, + }, + }, + Required: []string{"manifest"}, + }, + }, + Dependencies: []string{ + "github.com/otto8-ai/otto8/apiclient/types.DefaultModelAliasManifest"}, + } +} + +func schema_storage_apis_ottootto8ai_v1_DefaultModelAliasStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "setAliasName": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"setAliasName"}, + }, + }, + } +} + func schema_storage_apis_ottootto8ai_v1_EmailReceiver(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -4572,6 +4975,13 @@ func schema_storage_apis_ottootto8ai_v1_KnowledgeSetSpec(ref common.ReferenceCal Format: "", }, }, + "textEmbeddingModel": { + SchemaProps: spec.SchemaProps{ + Description: "TextEmbeddingModel is set when the model is predetermined on creation. For example, agent threads.", + Type: []string{"string"}, + Format: "", + }, + }, }, }, }, @@ -4610,6 +5020,18 @@ func schema_storage_apis_ottootto8ai_v1_KnowledgeSetStatus(ref common.ReferenceC Format: "", }, }, + "existingFile": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + "textEmbeddingModel": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, }, }, }, @@ -5899,6 +6321,12 @@ func schema_storage_apis_ottootto8ai_v1_ThreadSpec(ref common.ReferenceCallback) Format: "", }, }, + "textEmbeddingModel": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, "systemTask": { SchemaProps: spec.SchemaProps{ Type: []string{"boolean"}, @@ -6727,6 +7155,18 @@ func schema_storage_apis_ottootto8ai_v1_WorkflowSpec(ref common.ReferenceCallbac SchemaProps: spec.SchemaProps{ Type: []string{"object"}, Properties: map[string]spec.Schema{ + "agentName": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + "userID": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, "manifest": { SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, diff --git a/pkg/system/ids.go b/pkg/system/ids.go index 0ce338b4c..3b7e56f81 100644 --- a/pkg/system/ids.go +++ b/pkg/system/ids.go @@ -19,6 +19,7 @@ const ( EmailReceiverPrefix = "er1" ModelPrefix = "m1" AliasPrefix = "al1" + DefaultModelAliasPrefix = "dma1" ) func IsThreadID(id string) bool { diff --git a/ui/admin/app/components/agent/AgentForm.tsx b/ui/admin/app/components/agent/AgentForm.tsx index 0545ab521..b5b59d4d5 100644 --- a/ui/admin/app/components/agent/AgentForm.tsx +++ b/ui/admin/app/components/agent/AgentForm.tsx @@ -5,6 +5,7 @@ import { useForm } from "react-hook-form"; import useSWR from "swr"; import { z } from "zod"; +import { ModelUsage } from "~/lib/model/models"; import { ModelApiService } from "~/lib/service/api/modelApiService"; import { TypographyH4 } from "~/components/Typography"; @@ -49,7 +50,9 @@ export function AgentForm({ agent, onSubmit, onChange }: AgentFormProps) { const models = useMemo(() => { if (!getModels.data) return []; - return getModels.data.filter((m) => !m.usage || m.usage === "agent"); + return getModels.data.filter( + (m) => !m.usage || m.usage === ModelUsage.LLM + ); }, [getModels.data]); const form = useForm({ diff --git a/ui/admin/app/components/model/ModelForm.tsx b/ui/admin/app/components/model/ModelForm.tsx index ffb2982ef..87bd2423a 100644 --- a/ui/admin/app/components/model/ModelForm.tsx +++ b/ui/admin/app/components/model/ModelForm.tsx @@ -72,7 +72,7 @@ export function ModelForm(props: ModelFormProps) { modelProvider: model?.modelProvider ?? "", active: model?.active ?? true, default: model?.default ?? false, - usage: model?.usage ?? "agent", + usage: model?.usage ?? ModelUsage.LLM, }; }, [model]); diff --git a/ui/admin/app/lib/model/models.ts b/ui/admin/app/lib/model/models.ts index dade1986f..5486dd7a7 100644 --- a/ui/admin/app/lib/model/models.ts +++ b/ui/admin/app/lib/model/models.ts @@ -3,14 +3,14 @@ import { z } from "zod"; import { EntityMeta } from "~/lib/model/primitives"; export const ModelUsage = { - Agent: "agent", + LLM: "llm", TextEmbedding: "text-embedding", ImageGeneration: "image-generation", } as const; export type ModelUsage = (typeof ModelUsage)[keyof typeof ModelUsage]; const ModelUsageLabels = { - [ModelUsage.Agent]: "Agent", + [ModelUsage.LLM]: "LLM", [ModelUsage.TextEmbedding]: "Text Embedding", [ModelUsage.ImageGeneration]: "Image Generation", } as const;