diff --git a/apiclient/agent.go b/apiclient/agent.go index 8230442e..726f86d4 100644 --- a/apiclient/agent.go +++ b/apiclient/agent.go @@ -63,7 +63,7 @@ func (c *Client) ListAgents(ctx context.Context, opts ListAgentsOptions) (result if opts.Alias != "" { var filtered types.AgentList for _, agent := range result.Items { - if agent.Alias == opts.Alias && agent.AliasAssigned { + if agent.Alias == opts.Alias && agent.AliasAssigned != nil && *agent.AliasAssigned { filtered.Items = append(filtered.Items, agent) } } diff --git a/apiclient/types/agent.go b/apiclient/types/agent.go index bc7f14a1..e8d5d6dd 100644 --- a/apiclient/types/agent.go +++ b/apiclient/types/agent.go @@ -11,7 +11,7 @@ import ( type Agent struct { Metadata AgentManifest - AliasAssigned bool `json:"aliasAssigned,omitempty"` + AliasAssigned *bool `json:"aliasAssigned,omitempty"` AuthStatus map[string]OAuthAppLoginAuthStatus `json:"authStatus,omitempty"` TextEmbeddingModel string `json:"textEmbeddingModel,omitempty"` } diff --git a/apiclient/types/emailreceiver.go b/apiclient/types/emailreceiver.go index e653d783..366e2f63 100644 --- a/apiclient/types/emailreceiver.go +++ b/apiclient/types/emailreceiver.go @@ -3,7 +3,7 @@ package types type EmailReceiver struct { Metadata EmailReceiverManifest - AddressAssigned bool `json:"aliasAssigned,omitempty"` + AddressAssigned *bool `json:"aliasAssigned,omitempty"` EmailAddress string `json:"emailAddress,omitempty"` } diff --git a/apiclient/types/model.go b/apiclient/types/model.go index d2d6ba4c..4d644788 100644 --- a/apiclient/types/model.go +++ b/apiclient/types/model.go @@ -19,7 +19,7 @@ type ModelList List[Model] type ModelStatus struct { ModelProviderStatus - AliasAssigned bool `json:"aliasAssigned,omitempty"` + AliasAssigned *bool `json:"aliasAssigned,omitempty"` } type ModelProviderStatus struct { diff --git a/apiclient/types/webhook.go b/apiclient/types/webhook.go index 6be74d78..4fd07880 100644 --- a/apiclient/types/webhook.go +++ b/apiclient/types/webhook.go @@ -3,7 +3,7 @@ package types type Webhook struct { Metadata WebhookManifest - AliasAssigned bool `json:"aliasAssigned,omitempty"` + AliasAssigned *bool `json:"aliasAssigned,omitempty"` LastSuccessfulRunCompleted *Time `json:"lastSuccessfulRunCompleted,omitempty"` HasToken bool `json:"hasToken,omitempty"` } diff --git a/apiclient/types/workflow.go b/apiclient/types/workflow.go index 64b104dd..3fe0dbfe 100644 --- a/apiclient/types/workflow.go +++ b/apiclient/types/workflow.go @@ -5,7 +5,7 @@ import "strings" type Workflow struct { Metadata WorkflowManifest - AliasAssigned bool `json:"aliasAssigned,omitempty"` + AliasAssigned *bool `json:"aliasAssigned,omitempty"` AuthStatus map[string]OAuthAppLoginAuthStatus `json:"authStatus,omitempty"` TextEmbeddingModel string `json:"textEmbeddingModel,omitempty"` } diff --git a/apiclient/types/zz_generated.deepcopy.go b/apiclient/types/zz_generated.deepcopy.go index 184ddb0f..773b3160 100644 --- a/apiclient/types/zz_generated.deepcopy.go +++ b/apiclient/types/zz_generated.deepcopy.go @@ -13,6 +13,11 @@ func (in *Agent) DeepCopyInto(out *Agent) { *out = *in in.Metadata.DeepCopyInto(&out.Metadata) in.AgentManifest.DeepCopyInto(&out.AgentManifest) + if in.AliasAssigned != nil { + in, out := &in.AliasAssigned, &out.AliasAssigned + *out = new(bool) + **out = **in + } if in.AuthStatus != nil { in, out := &in.AuthStatus, &out.AuthStatus *out = make(map[string]OAuthAppLoginAuthStatus, len(*in)) @@ -383,6 +388,11 @@ func (in *EmailReceiver) DeepCopyInto(out *EmailReceiver) { *out = *in in.Metadata.DeepCopyInto(&out.Metadata) in.EmailReceiverManifest.DeepCopyInto(&out.EmailReceiverManifest) + if in.AddressAssigned != nil { + in, out := &in.AddressAssigned, &out.AddressAssigned + *out = new(bool) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EmailReceiver. @@ -834,6 +844,11 @@ func (in *ModelProviderStatus) DeepCopy() *ModelProviderStatus { func (in *ModelStatus) DeepCopyInto(out *ModelStatus) { *out = *in in.ModelProviderStatus.DeepCopyInto(&out.ModelProviderStatus) + if in.AliasAssigned != nil { + in, out := &in.AliasAssigned, &out.AliasAssigned + *out = new(bool) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ModelStatus. @@ -1680,6 +1695,11 @@ func (in *Webhook) DeepCopyInto(out *Webhook) { *out = *in in.Metadata.DeepCopyInto(&out.Metadata) in.WebhookManifest.DeepCopyInto(&out.WebhookManifest) + if in.AliasAssigned != nil { + in, out := &in.AliasAssigned, &out.AliasAssigned + *out = new(bool) + **out = **in + } if in.LastSuccessfulRunCompleted != nil { in, out := &in.LastSuccessfulRunCompleted, &out.LastSuccessfulRunCompleted *out = (*in).DeepCopy() @@ -1785,6 +1805,11 @@ func (in *Workflow) DeepCopyInto(out *Workflow) { *out = *in in.Metadata.DeepCopyInto(&out.Metadata) in.WorkflowManifest.DeepCopyInto(&out.WorkflowManifest) + if in.AliasAssigned != nil { + in, out := &in.AliasAssigned, &out.AliasAssigned + *out = new(bool) + **out = **in + } if in.AuthStatus != nil { in, out := &in.AuthStatus, &out.AuthStatus *out = make(map[string]OAuthAppLoginAuthStatus, len(*in)) diff --git a/apiclient/workflow.go b/apiclient/workflow.go index 1c8c524d..e43157c6 100644 --- a/apiclient/workflow.go +++ b/apiclient/workflow.go @@ -63,7 +63,7 @@ func (c *Client) ListWorkflows(ctx context.Context, opts ListWorkflowsOptions) ( if opts.Alias != "" { var filtered types.WorkflowList for _, workflow := range result.Items { - if workflow.Alias == opts.Alias && workflow.AliasAssigned { + if workflow.Alias == opts.Alias && workflow.AliasAssigned != nil && *workflow.AliasAssigned { filtered.Items = append(filtered.Items, workflow) } } diff --git a/pkg/api/handlers/agent.go b/pkg/api/handlers/agent.go index 122bcebc..d789aabd 100644 --- a/pkg/api/handlers/agent.go +++ b/pkg/api/handlers/agent.go @@ -53,14 +53,7 @@ func (a *AgentHandler) Update(req api.Context) error { return err } - processedAgent, err := wait.For(req.Context(), req.Storage, &agent, func(agent *v1.Agent) (bool, error) { - return agent.Generation == agent.Status.AliasObservedGeneration, nil - }) - if err != nil { - return fmt.Errorf("failed to update agent: %w", err) - } - - resp, err := convertAgent(*processedAgent, req) + resp, err := convertAgent(agent, req) if err != nil { return err } @@ -91,17 +84,15 @@ func (a *AgentHandler) Create(req api.Context) error { }, } - agent, err := wait.For(req.Context(), req.Storage, agent, func(agent *v1.Agent) (bool, error) { - return agent.Generation == agent.Status.AliasObservedGeneration, nil - }, wait.Option{Create: true}) - if err != nil { - return fmt.Errorf("failed to create agent: %w", err) + if err := req.Create(agent); err != nil { + return err } resp, err := convertAgent(*agent, req) if err != nil { return err } + return req.WriteCreated(resp) } @@ -125,10 +116,15 @@ func convertAgent(agent v1.Agent, req api.Context) (*types.Agent, error) { } } + var aliasAssigned *bool + if agent.Generation == agent.Status.AliasObservedGeneration { + aliasAssigned = &agent.Status.AliasAssigned + } + return &types.Agent{ Metadata: MetadataFrom(&agent, links...), AgentManifest: agent.Spec.Manifest, - AliasAssigned: agent.Status.AliasAssigned, + AliasAssigned: aliasAssigned, AuthStatus: agent.Status.AuthStatus, TextEmbeddingModel: embeddingModel, }, nil diff --git a/pkg/api/handlers/emailreceiver.go b/pkg/api/handlers/emailreceiver.go index 81d56ed3..03144427 100644 --- a/pkg/api/handlers/emailreceiver.go +++ b/pkg/api/handlers/emailreceiver.go @@ -1,14 +1,11 @@ package handlers import ( - "fmt" - "github.com/otto8-ai/otto8/apiclient/types" "github.com/otto8-ai/otto8/pkg/alias" "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" - "github.com/otto8-ai/otto8/pkg/wait" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -42,14 +39,7 @@ func (e *EmailReceiverHandler) Update(req api.Context) error { return err } - processedEr, err := wait.For(req.Context(), req.Storage, &er, func(er *v1.EmailReceiver) (bool, error) { - return er.Generation == er.Status.AliasObservedGeneration, nil - }) - if err != nil { - return fmt.Errorf("failed to update email receiver: %w", err) - } - - return req.Write(convertEmailReceiver(*processedEr, e.hostname)) + return req.Write(convertEmailReceiver(er, e.hostname)) } func (e *EmailReceiverHandler) Delete(req api.Context) error { @@ -81,11 +71,8 @@ func (e *EmailReceiverHandler) Create(req api.Context) error { }, } - er, err := wait.For(req.Context(), req.Storage, er, func(er *v1.EmailReceiver) (bool, error) { - return er.Generation == er.Status.AliasObservedGeneration, nil - }, wait.Option{Create: true}) - if err != nil { - return fmt.Errorf("failed to create email receiver: %w", err) + if err := req.Create(er); err != nil { + return err } return req.WriteCreated(convertEmailReceiver(*er, e.hostname)) @@ -93,12 +80,17 @@ func (e *EmailReceiverHandler) Create(req api.Context) error { func convertEmailReceiver(emailReceiver v1.EmailReceiver, hostname string) *types.EmailReceiver { manifest := emailReceiver.Spec.EmailReceiverManifest + + var aliasAssigned *bool + if emailReceiver.Generation == emailReceiver.Status.AliasObservedGeneration { + aliasAssigned = &emailReceiver.Status.AliasAssigned + } er := &types.EmailReceiver{ Metadata: MetadataFrom(&emailReceiver), EmailReceiverManifest: manifest, - AddressAssigned: emailReceiver.Status.AliasAssigned, + AddressAssigned: aliasAssigned, } - if hostname != "" && er.AddressAssigned { + if hostname != "" && er.AddressAssigned != nil && *er.AddressAssigned { er.EmailAddress = emailReceiver.Spec.User + "@" + hostname } return er diff --git a/pkg/api/handlers/model.go b/pkg/api/handlers/model.go index 8f8a5129..f9820667 100644 --- a/pkg/api/handlers/model.go +++ b/pkg/api/handlers/model.go @@ -13,7 +13,6 @@ import ( v1 "github.com/otto8-ai/otto8/pkg/storage/apis/otto.otto8.ai/v1" "github.com/otto8-ai/otto8/pkg/storage/selectors" "github.com/otto8-ai/otto8/pkg/system" - "github.com/otto8-ai/otto8/pkg/wait" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" kclient "sigs.k8s.io/controller-runtime/pkg/client" @@ -79,14 +78,7 @@ func (a *ModelHandler) Update(req api.Context) error { return err } - processedModel, err := wait.For(req.Context(), req.Storage, &existing, func(model *v1.Model) (bool, error) { - return model.Generation == model.Status.AliasObservedGeneration, nil - }) - if err != nil { - return fmt.Errorf("failed to update model: %w", err) - } - - resp, err := convertModel(req.Context(), req.Storage, *processedModel) + resp, err := convertModel(req.Context(), req.Storage, existing) if err != nil { return err } @@ -127,11 +119,8 @@ func (a *ModelHandler) Create(req api.Context) error { return err } - model, err := wait.For(req.Context(), req.Storage, model, func(model *v1.Model) (bool, error) { - return model.Generation == model.Status.AliasObservedGeneration, nil - }, wait.Option{Create: true}) - if err != nil { - return fmt.Errorf("failed to create model: %w", err) + if err := req.Create(model); err != nil { + return err } resp, err := convertModel(req.Context(), req.Storage, *model) @@ -172,12 +161,17 @@ func convertModel(ctx context.Context, c kclient.Client, model v1.Model) (types. return types.Model{}, err } + var aliasAssigned *bool + if model.Generation == model.Status.AliasObservedGeneration { + aliasAssigned = &model.Status.AliasAssigned + } + return types.Model{ Metadata: MetadataFrom(&model), ModelManifest: model.Spec.Manifest, ModelStatus: types.ModelStatus{ ModelProviderStatus: *convertModelProviderToolRef(toolRef), - AliasAssigned: model.Status.AliasAssigned, + AliasAssigned: aliasAssigned, }, }, nil } diff --git a/pkg/api/handlers/webhooks.go b/pkg/api/handlers/webhooks.go index b9374b05..07a5bbfc 100644 --- a/pkg/api/handlers/webhooks.go +++ b/pkg/api/handlers/webhooks.go @@ -15,7 +15,6 @@ import ( "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" - "github.com/otto8-ai/otto8/pkg/wait" "golang.org/x/crypto/bcrypt" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -78,14 +77,7 @@ func (a *WebhookHandler) Update(req api.Context) error { return err } - processedWh, err := wait.For(req.Context(), req.Storage, &wh, func(wh *v1.Webhook) (bool, error) { - return wh.Generation == wh.Status.AliasObservedGeneration, nil - }) - if err != nil { - return fmt.Errorf("failed to update webhook: %w", err) - } - - return req.Write(convertWebhook(*processedWh, req.APIBaseURL)) + return req.Write(convertWebhook(wh, req.APIBaseURL)) } func (a *WebhookHandler) Delete(req api.Context) error { @@ -130,11 +122,8 @@ func (a *WebhookHandler) Create(req api.Context) error { wh.Spec.Headers[i] = textproto.CanonicalMIMEHeaderKey(h) } - wh, err := wait.For(req.Context(), req.Storage, wh, func(wh *v1.Webhook) (bool, error) { - return wh.Generation == wh.Status.AliasObservedGeneration, nil - }, wait.Option{Create: true}) - if err != nil { - return fmt.Errorf("failed to create webhook: %w", err) + if err := req.Create(wh); err != nil { + return err } return req.WriteCreated(convertWebhook(*wh, req.APIBaseURL)) @@ -150,11 +139,16 @@ func convertWebhook(webhook v1.Webhook, urlPrefix string) *types.Webhook { links = []string{"invoke", fmt.Sprintf("%s/webhooks/%s/%s", urlPrefix, webhook.Namespace, path)} } + var aliasAssigned *bool + if webhook.Generation == webhook.Status.AliasObservedGeneration { + aliasAssigned = &webhook.Status.AliasAssigned + } + manifest := webhook.Spec.WebhookManifest wh := &types.Webhook{ Metadata: MetadataFrom(&webhook, links...), WebhookManifest: manifest, - AliasAssigned: webhook.Status.AliasAssigned, + AliasAssigned: aliasAssigned, LastSuccessfulRunCompleted: v1.NewTime(webhook.Status.LastSuccessfulRunCompleted), HasToken: len(webhook.Spec.TokenHash) > 0, } diff --git a/pkg/api/handlers/workflows.go b/pkg/api/handlers/workflows.go index a34e2f78..51370ffa 100644 --- a/pkg/api/handlers/workflows.go +++ b/pkg/api/handlers/workflows.go @@ -89,14 +89,7 @@ func (a *WorkflowHandler) Update(req api.Context) error { return err } - processedWf, err := wait.For(req.Context(), req.Storage, &wf, func(wf *v1.Workflow) (bool, error) { - return wf.Generation == wf.Status.AliasObservedGeneration, nil - }) - if err != nil { - return fmt.Errorf("failed to update workflow: %w", err) - } - - resp, err := convertWorkflow(*processedWf, req) + resp, err := convertWorkflow(wf, req) if err != nil { return err } @@ -134,11 +127,8 @@ func (a *WorkflowHandler) Create(req api.Context) error { }, } - wf, err := wait.For(req.Context(), req.Storage, wf, func(wf *v1.Workflow) (bool, error) { - return wf.Generation == wf.Status.AliasObservedGeneration, nil - }, wait.Option{Create: true}) - if err != nil { - return fmt.Errorf("failed to create workflow: %w", err) + if err := req.Create(wf); err != nil { + return err } resp, err := convertWorkflow(*wf, req) @@ -169,10 +159,15 @@ func convertWorkflow(workflow v1.Workflow, req api.Context) (*types.Workflow, er } } + var aliasAssigned *bool + if workflow.Generation == workflow.Status.AliasObservedGeneration { + aliasAssigned = &workflow.Status.AliasAssigned + } + return &types.Workflow{ Metadata: MetadataFrom(&workflow, links...), WorkflowManifest: workflow.Spec.Manifest, - AliasAssigned: workflow.Status.AliasAssigned, + AliasAssigned: aliasAssigned, AuthStatus: workflow.Status.AuthStatus, TextEmbeddingModel: embeddingModel, }, nil diff --git a/pkg/storage/openapi/generated/openapi_generated.go b/pkg/storage/openapi/generated/openapi_generated.go index 82d0f76d..aec10d7b 100644 --- a/pkg/storage/openapi/generated/openapi_generated.go +++ b/pkg/storage/openapi/generated/openapi_generated.go @@ -3092,6 +3092,12 @@ func schema_otto8_ai_otto8_apiclient_types_Thread(ref common.ReferenceCallback) Format: "", }, }, + "abort": { + SchemaProps: spec.SchemaProps{ + Type: []string{"boolean"}, + Format: "", + }, + }, }, Required: []string{"Metadata", "ThreadManifest"}, }, @@ -6656,6 +6662,12 @@ func schema_storage_apis_ottootto8ai_v1_ThreadSpec(ref common.ReferenceCallback) Format: "", }, }, + "abort": { + SchemaProps: spec.SchemaProps{ + Type: []string{"boolean"}, + Format: "", + }, + }, }, }, },