Skip to content

Commit

Permalink
fix: use custom oauth configurations for knowledge syncing (#597)
Browse files Browse the repository at this point in the history
Signed-off-by: Donnie Adams <[email protected]>
  • Loading branch information
thedadams authored Nov 15, 2024
1 parent fdad35a commit 5032564
Show file tree
Hide file tree
Showing 11 changed files with 52 additions and 18 deletions.
9 changes: 5 additions & 4 deletions pkg/api/handlers/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ func (a *AgentHandler) CreateKnowledgeSource(req api.Context) error {

var input types.KnowledgeSourceManifest
if err := req.Read(&input); err != nil {
return types.NewErrBadRequest("failed to decode request body: %w", err)
return types.NewErrBadRequest("failed to decode request body: %v", err)
}

if err := input.Validate(); err != nil {
Expand All @@ -312,7 +312,7 @@ func (a *AgentHandler) CreateKnowledgeSource(req api.Context) error {
}

if err := req.Create(&source); err != nil {
return types.NewErrBadRequest("failed to create RemoteKnowledgeSource: %w", err)
return types.NewErrBadRequest("failed to create RemoteKnowledgeSource: %v", err)
}

return req.Write(convertKnowledgeSource(agentName, source))
Expand All @@ -326,7 +326,7 @@ func (a *AgentHandler) UpdateKnowledgeSource(req api.Context) error {

var manifest types.KnowledgeSourceManifest
if err := req.Read(&manifest); err != nil {
return types.NewErrBadRequest("failed to decode request body: %w", err)
return types.NewErrBadRequest("failed to decode request body: %v", err)
}

if err := manifest.Validate(); err != nil {
Expand Down Expand Up @@ -535,6 +535,7 @@ func (a *AgentHandler) EnsureCredentialForKnowledgeSource(req api.Context) error
Spec: v1.OAuthAppLoginSpec{
CredentialContext: agent.Name,
ToolReference: ref,
OAuthApps: agent.Spec.Manifest.OAuthApps,
},
}

Expand Down Expand Up @@ -566,7 +567,7 @@ func (a *AgentHandler) Script(req api.Context) error {
agent v1.Agent
)
if err := req.Get(&agent, id); err != nil {
return types.NewErrBadRequest("failed to get agent with id %s: %w", id, err)
return types.NewErrBadRequest("failed to get agent with id %s: %v", id, err)
}

tools, extraEnv, err := render.Agent(req.Context(), req.Storage, &agent, a.serverURL, render.AgentOptions{})
Expand Down
2 changes: 1 addition & 1 deletion pkg/api/handlers/assistants.go
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ func (a *AssistantHandler) DeleteKnowledge(req api.Context) error {
}

if len(thread.Status.KnowledgeSetNames) == 0 {
return types.NewErrHttp(http.StatusTooEarly, fmt.Sprintf("knowledge set is not created yet"))
return types.NewErrHttp(http.StatusTooEarly, "knowledge set is not created yet")
}

return deleteKnowledge(req, req.PathValue("file"), thread.Status.KnowledgeSetNames[0])
Expand Down
4 changes: 2 additions & 2 deletions pkg/api/handlers/webhooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ func validateSecretHeader(secret string, body []byte, values []string) error {
func validateManifest(req api.Context, manifest types.WebhookManifest) error {
// Ensure that the WorkflowID is set and the workflow exists
if manifest.WorkflowID == "" {
return apierrors.NewBadRequest(fmt.Sprintf("webhook manifest must have a workflow name"))
return apierrors.NewBadRequest("webhook manifest must have a workflow name")
}

var workflow v1.Workflow
Expand All @@ -297,7 +297,7 @@ func validateManifest(req api.Context, manifest types.WebhookManifest) error {
}

if (manifest.ValidationHeader != "") != (manifest.Secret != "") {
return apierrors.NewBadRequest(fmt.Sprintf("webhook must have secret and header set together"))
return apierrors.NewBadRequest("webhook must have secret and header set together")
}

return nil
Expand Down
1 change: 1 addition & 0 deletions pkg/api/handlers/workflows.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ func (a *WorkflowHandler) EnsureCredentialForKnowledgeSource(req api.Context) er
Spec: v1.OAuthAppLoginSpec{
CredentialContext: wf.Name,
ToolReference: ref,
OAuthApps: wf.Spec.Manifest.OAuthApps,
},
}

Expand Down
15 changes: 12 additions & 3 deletions pkg/controller/handlers/oauthapp/oauthapplogin.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/otto8-ai/nah/pkg/router"
"github.com/otto8-ai/otto8/apiclient/types"
"github.com/otto8-ai/otto8/pkg/invoke"
"github.com/otto8-ai/otto8/pkg/render"
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"
Expand All @@ -16,12 +17,14 @@ import (
)

type LoginHandler struct {
invoker *invoke.Invoker
invoker *invoke.Invoker
serverURL string
}

func NewLogin(invoker *invoke.Invoker) *LoginHandler {
func NewLogin(invoker *invoke.Invoker, serverURL string) *LoginHandler {
return &LoginHandler{
invoker: invoker,
invoker: invoker,
serverURL: serverURL,
}
}

Expand Down Expand Up @@ -50,13 +53,19 @@ func (h *LoginHandler) RunTool(req router.Request, _ router.Response) error {
return err
}

oauthAppEnv, err := render.OAuthAppEnv(req.Ctx, req.Client, login.Spec.OAuthApps, login.Namespace, h.serverURL)
if err != nil {
return err
}

task, err := h.invoker.SystemTask(req.Ctx, &thread, []gptscript.ToolDef{
{
Credentials: []string{credentialTool},
Instructions: "#!sys.echo DONE",
},
}, "", invoke.SystemTaskOptions{
CredentialContextIDs: []string{login.Spec.CredentialContext},
Env: oauthAppEnv,
})
if err != nil {
return err
Expand Down
2 changes: 1 addition & 1 deletion pkg/controller/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func (c *Controller) setupRoutes() error {
runs := runs.New(c.services.Invoker)
webHooks := webhook.New()
cronJobs := cronjob.New()
oauthLogins := oauthapp.NewLogin(c.services.Invoker)
oauthLogins := oauthapp.NewLogin(c.services.Invoker, c.services.ServerURL)

// Runs
root.Type(&v1.Run{}).FinalizeFunc(v1.RunFinalizer, runs.DeleteRunState)
Expand Down
3 changes: 3 additions & 0 deletions pkg/invoke/system.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ import (

type SystemTaskOptions struct {
CredentialContextIDs []string
Env []string
}

func complete(opts []SystemTaskOptions) (result SystemTaskOptions) {
for _, opt := range opts {
result.CredentialContextIDs = append(result.CredentialContextIDs, opt.CredentialContextIDs...)
result.Env = append(result.Env, opt.Env...)
}
return
}
Expand Down Expand Up @@ -42,6 +44,7 @@ func (i *Invoker) SystemTask(ctx context.Context, thread *v1.Thread, tool, input
}

return i.createRun(ctx, i.uncached, thread, tool, inputString, runOptions{
Env: opt.Env,
CredentialContextIDs: opt.CredentialContextIDs,
Synchronous: true,
})
Expand Down
8 changes: 4 additions & 4 deletions pkg/render/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func Agent(ctx context.Context, db kclient.Client, agent *v1.Agent, oauthServerU
return nil, nil, err
}

if oauthEnv, err := setupOAuthApps(ctx, db, agent, oauthServerURL); err != nil {
if oauthEnv, err := OAuthAppEnv(ctx, db, agent.Spec.Manifest.OAuthApps, agent.Namespace, oauthServerURL); err != nil {
return nil, nil, err
} else {
extraEnv = append(extraEnv, oauthEnv...)
Expand All @@ -87,8 +87,8 @@ func Agent(ctx context.Context, db kclient.Client, agent *v1.Agent, oauthServerU
return append([]gptscript.ToolDef{mainTool}, otherTools...), extraEnv, nil
}

func setupOAuthApps(ctx context.Context, db kclient.Client, agent *v1.Agent, serverURL string) (extraEnv []string, _ error) {
apps, err := oauthAppsByName(ctx, db, agent.Namespace)
func OAuthAppEnv(ctx context.Context, db kclient.Client, oauthAppNames []string, namespace, serverURL string) (extraEnv []string, _ error) {
apps, err := oauthAppsByName(ctx, db, namespace)
if err != nil {
return nil, err
}
Expand All @@ -102,7 +102,7 @@ func setupOAuthApps(ctx context.Context, db kclient.Client, agent *v1.Agent, ser
activeIntegrations[app.Spec.Manifest.Integration] = app
}

for _, appRef := range agent.Spec.Manifest.OAuthApps {
for _, appRef := range oauthAppNames {
app, ok := apps[appRef]
if !ok {
return nil, fmt.Errorf("oauth app %s not found", appRef)
Expand Down
5 changes: 3 additions & 2 deletions pkg/storage/apis/otto.otto8.ai/v1/oauthapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,9 @@ func (o *OAuthAppLogin) DeleteRefs() []Ref {
}

type OAuthAppLoginSpec struct {
CredentialContext string `json:"credentialContext,omitempty"`
ToolReference string `json:"toolReference,omitempty"`
CredentialContext string `json:"credentialContext,omitempty"`
ToolReference string `json:"toolReference,omitempty"`
OAuthApps []string `json:"oauthApps,omitempty"`
}

type OAuthAppLoginStatus struct {
Expand Down
7 changes: 6 additions & 1 deletion pkg/storage/apis/otto.otto8.ai/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions pkg/storage/openapi/generated/openapi_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 5032564

Please sign in to comment.