Skip to content

Commit

Permalink
chore: enhancements for otto8
Browse files Browse the repository at this point in the history
  • Loading branch information
ibuildthecloud committed Jan 20, 2025
1 parent 9784c73 commit 4db3511
Show file tree
Hide file tree
Showing 21 changed files with 190 additions and 115 deletions.
1 change: 1 addition & 0 deletions apiclient/types/thread.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type Thread struct {
UserID string `json:"userID,omitempty"`
AgentAlias string `json:"agentAlias,omitempty"`
Abort bool `json:"abort,omitempty"`
SystemTask bool `json:"systemTask,omitempty"`
Env []string `json:"env,omitempty"`
}

Expand Down
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ require (
github.com/gptscript-ai/chat-completion-client v0.0.0-20241219123536-85c44096bc10
github.com/gptscript-ai/cmd v0.0.0-20240907001148-ffd49061124a
github.com/gptscript-ai/go-gptscript v0.9.6-0.20241216211344-79a66826cf82
github.com/gptscript-ai/gptscript v0.9.6-0.20250114054318-73a9ffeb1cc8
github.com/gptscript-ai/gptscript v0.9.6-0.20250120172457-3f876b2ef42b
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de
github.com/mhale/smtpd v0.8.3
github.com/oauth2-proxy/oauth2-proxy/v7 v7.0.0-00010101000000-000000000000
Expand Down Expand Up @@ -232,6 +232,7 @@ require (
github.com/spf13/viper v1.19.0 // indirect
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
github.com/stoewer/go-strcase v1.2.0 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/therootcompany/xz v1.0.1 // indirect
github.com/tidwall/gjson v1.18.0 // indirect
Expand Down
7 changes: 4 additions & 3 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -353,8 +353,8 @@ github.com/gptscript-ai/cmd v0.0.0-20240907001148-ffd49061124a h1:LX7AOcbBoTnUk/
github.com/gptscript-ai/cmd v0.0.0-20240907001148-ffd49061124a/go.mod h1:DJAo1xTht1LDkNYFNydVjTHd576TC7MlpsVRl3oloVw=
github.com/gptscript-ai/go-gptscript v0.9.6-0.20241216211344-79a66826cf82 h1:BEN268Z92gqeDc51XVvWdJWdQ47BuuWH3MUysHzilfI=
github.com/gptscript-ai/go-gptscript v0.9.6-0.20241216211344-79a66826cf82/go.mod h1:/FVuLwhz+sIfsWUgUHWKi32qT0i6+IXlUlzs70KKt/Q=
github.com/gptscript-ai/gptscript v0.9.6-0.20250114054318-73a9ffeb1cc8 h1:UNtUJkRTKj35jRFK59ndd3O9NFPfk5OzrYl2boUqFqM=
github.com/gptscript-ai/gptscript v0.9.6-0.20250114054318-73a9ffeb1cc8/go.mod h1:eBrKu1mmZ4tLPoHJJD1xT/Ogm5K7Oue14xk54e+yEZw=
github.com/gptscript-ai/gptscript v0.9.6-0.20250120172457-3f876b2ef42b h1:xOnA8rGg3iGjTpvWUtuw8IzPFey5gsivi1CUNtZp4Gc=
github.com/gptscript-ai/gptscript v0.9.6-0.20250120172457-3f876b2ef42b/go.mod h1:eBrKu1mmZ4tLPoHJJD1xT/Ogm5K7Oue14xk54e+yEZw=
github.com/gptscript-ai/tui v0.0.0-20240923192013-172e51ccf1d6 h1:vkgNZVWQgbE33VD3z9WKDwuu7B/eJVVMMPM62ixfCR8=
github.com/gptscript-ai/tui v0.0.0-20240923192013-172e51ccf1d6/go.mod h1:frrl/B+ZH3VSs3Tqk2qxEIIWTONExX3tuUa4JsVnqx4=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM=
Expand Down Expand Up @@ -633,8 +633,9 @@ github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ai
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
Expand Down
6 changes: 6 additions & 0 deletions pkg/api/authz/assistant.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package authz

import (
"net/http"
"slices"
"strings"

"github.com/obot-platform/obot/pkg/alias"
Expand All @@ -20,6 +21,11 @@ func (a *Authorizer) authorizeAssistant(req *http.Request, user user.Info) bool
return false
}

// Must be authenticated
if !slices.Contains(user.GetGroups(), AuthenticatedGroup) {
return false
}

var (
agentID = paths[3]
keys = make([]string, 0, 3)
Expand Down
1 change: 1 addition & 0 deletions pkg/api/handlers/threads.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ func convertThread(thread v1.Thread) types.Thread {
AgentAlias: thread.Spec.AgentAlias,
UserID: thread.Spec.UserUID,
Abort: thread.Spec.Abort,
SystemTask: thread.Spec.SystemTask,
Env: thread.Spec.Env,
}
}
Expand Down
69 changes: 42 additions & 27 deletions pkg/api/handlers/tools.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package handlers

import (
"context"
"errors"
"maps"
"regexp"
"slices"
"time"

"github.com/gptscript-ai/go-gptscript"
"github.com/obot-platform/obot/apiclient/types"
Expand Down Expand Up @@ -142,68 +144,81 @@ type TestInput struct {
}

func (t *ToolHandler) Test(req api.Context) error {
toolID := req.PathValue("tool_id")
var (
toolID = req.PathValue("tool_id")
agent v1.Agent
envs []string
envNameList []string
testID = system.ToolPrefix + "-test-cred"
)

thread, err := getThreadForScope(req)
if err != nil {
return err
}

var tool v1.Tool
if err := req.Get(&tool, toolID); err != nil {
if err := req.Get(&agent, thread.Spec.AgentName); err != nil {
return err
}

if tool.Spec.ThreadName != thread.Name {
return types.NewErrNotFound("tool %s not found", toolID)
for _, env := range agent.Spec.Manifest.Env {
if env.Name != "" && env.Value != "" {
envs = append(envs, env.Name+"="+env.Value)
}
}

env, err := getEnvMap(req, t.gptScript, thread.Name, tool.Name)
if err != nil {
var tool v1.Tool
if err := req.Get(&tool, toolID); err != nil {
return err
}

var (
envNameList []string
envNameSeen = map[string]struct{}{}
)
var envList []string
for k, v := range env {
envNameList = append(envNameList, k)
envNameSeen[k] = struct{}{}
envList = append(envList, k+"="+v)
if tool.Spec.ThreadName != thread.Name {
return types.NewErrNotFound("tool %s not found", toolID)
}

var input TestInput
if err := req.Read(&input); err != nil {
return err
}

for k, v := range input.Env {
if _, ok := envNameSeen[k]; !ok {
envNameList = append(envNameList, k)
envNameSeen[k] = struct{}{}
if len(input.Env) > 0 {
for envName := range input.Env {
if invalidEnv.MatchString(envName) {
return types.NewErrBadRequest("invalid env key %s", envName)
}
envNameList = append(envNameList, envName)
}
err := t.gptScript.CreateCredential(req.Context(), gptscript.Credential{
Context: thread.Name,
ToolName: testID,
Type: gptscript.CredentialTypeTool,
Env: input.Env,
})
if err != nil {
return err
}
envList = append(envList, k+"="+v)
defer func() {
_ = t.gptScript.DeleteCredential(req.Context(), thread.Name, testID)
}()
}

if input.Tool != nil {
tool.Spec.Manifest = input.Tool.ToolManifest
}

if tool.Spec.Manifest.Name == "" {
tool.Spec.Manifest.Name = "test"
}

tool.Spec.Manifest.Name = testID
tool.Spec.Envs = envNameList

tools, err := render.CustomTool(req.Context(), req.Storage, tool)
if err != nil {
return err
}

result, err := t.invoke.EphemeralThreadTask(req.Context(), thread, tools, input.Input, invoke.SystemTaskOptions{
Env: envList,
timeoutCtx, cancel := context.WithTimeout(req.Context(), 1*time.Minute)
defer cancel()

result, err := t.invoke.EphemeralThreadTask(timeoutCtx, thread, tools, input.Input, invoke.SystemTaskOptions{
Env: envs,
})
if err != nil {
return err
Expand Down
10 changes: 10 additions & 0 deletions pkg/controller/handlers/workflowexecution/workflowexecution.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,16 @@ func (h *Handler) loadManifest(req router.Request, we *v1.WorkflowExecution) err

func (h *Handler) newThread(ctx context.Context, c kclient.Client, wf *v1.Workflow, we *v1.WorkflowExecution) (*v1.Thread, error) {
workspaceName := we.Spec.WorkspaceName
if workspaceName == "" && wf.Spec.ThreadName != "" {
var thread v1.Thread
if err := c.Get(ctx, kclient.ObjectKey{Namespace: we.Namespace, Name: wf.Spec.ThreadName}, &thread); err != nil {
return nil, err
}
if thread.Status.WorkspaceName != "" {
workspaceName = thread.Status.WorkspaceName
}
}

if workspaceName == "" {
workspaceName = wf.Status.WorkspaceName
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/controller/handlers/workspace/workspace.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func getWorkspaceIDs(ctx context.Context, c kclient.WithWatch, ws *v1.Workspace)
if err := c.Get(ctx, router.Key(ws.Namespace, wsName), &dependentWS); err != nil || dependentWS.Status.WorkspaceID == "" {
return nil, false, err
}
wsIDs = append(wsIDs, ws.Status.WorkspaceID)
wsIDs = append(wsIDs, dependentWS.Status.WorkspaceID)
}

return wsIDs, true, nil
Expand Down
11 changes: 10 additions & 1 deletion pkg/invoke/system.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"strings"
"time"

"github.com/obot-platform/nah/pkg/router"
"github.com/obot-platform/obot/apiclient/types"
"github.com/obot-platform/obot/pkg/render"
v1 "github.com/obot-platform/obot/pkg/storage/apis/obot.obot.ai/v1"
Expand Down Expand Up @@ -45,6 +46,13 @@ func (i *Invoker) EphemeralThreadTask(ctx context.Context, thread *v1.Thread, to
return "", err
}

var agent v1.Agent
if thread.Spec.AgentName != "" {
if err := i.uncached.Get(ctx, router.Key(thread.Namespace, thread.Spec.AgentName), &agent); err != nil {
return "", err
}
}

tool, extraEnv, err = render.Agent(ctx, i.uncached, &v1.Agent{
ObjectMeta: metav1.ObjectMeta{
Namespace: thread.Namespace,
Expand All @@ -53,6 +61,7 @@ func (i *Invoker) EphemeralThreadTask(ctx context.Context, thread *v1.Thread, to
Manifest: types.AgentManifest{
Prompt: "#!sys.call " + toolRef,
Tools: []string{toolRef},
Env: agent.Spec.Manifest.Env,
},
},
}, i.serverURL, render.AgentOptions{
Expand All @@ -77,7 +86,7 @@ func (i *Invoker) EphemeralThreadTask(ctx context.Context, thread *v1.Thread, to
resp, err := i.createRun(ctx, i.uncached, thread, tool, inputString, runOptions{
Ephemeral: true,
Env: append(opt.Env, extraEnv...),
CredentialContextIDs: append(credContexts, opt.CredentialContextIDs...),
CredentialContextIDs: append(opt.CredentialContextIDs, credContexts...),
Synchronous: true,
Timeout: opt.Timeout,
})
Expand Down
2 changes: 1 addition & 1 deletion pkg/render/tool.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func CustomTool(ctx context.Context, c client.Client, tool v1.Tool) (toolDefs []
return nil, nil
}

if tool.Spec.Manifest.ToolType != "" && tool.Spec.Manifest.ToolType != "docker" && tool.Spec.Manifest.Instructions == "" {
if tool.Spec.Manifest.ToolType != "" && tool.Spec.Manifest.ToolType != "container" && tool.Spec.Manifest.Instructions == "" {
return nil, fmt.Errorf("instructions are required for custom tools")
}

Expand Down
6 changes: 6 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.

4 changes: 4 additions & 0 deletions ui/user/src/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,7 @@
body {
@apply bg-white text-black dark:bg-black dark:text-gray-50;
}

.text-input {
@apply w-full rounded-lg bg-gray-100 p-2 outline-none focus:ring-2 focus:ring-blue dark:bg-gray-900;
}
36 changes: 17 additions & 19 deletions ui/user/src/lib/components/Thread.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -54,25 +54,23 @@
>
<div class="flex w-full max-w-[900px] flex-col px-8 pt-24 transition-all">
<div in:fade|global class="flex flex-col gap-8">
{#if messages.messages.length < 7}
<div class="message-content self-center">
{#if assistant?.introductionMessage}
{@html toHTMLFromMarkdown(assistant.introductionMessage)}
{/if}
</div>
<div class="flex gap-2 self-center">
{#each assistant?.starterMessages ?? [] as msg}
<button
class="rounded-3xl border-2 border-blue p-5"
onclick={() => {
thread?.invoke(msg);
}}
>
{msg}
</button>
{/each}
</div>
{/if}
<div class="message-content self-center">
{#if assistant?.introductionMessage}
{@html toHTMLFromMarkdown(assistant.introductionMessage)}
{/if}
</div>
<div class="flex gap-2 self-center">
{#each assistant?.starterMessages ?? [] as msg}
<button
class="rounded-3xl border-2 border-blue p-5"
onclick={() => {
thread?.invoke(msg);
}}
>
{msg}
</button>
{/each}
</div>
{#each messages.messages as msg}
<Message {msg} {onLoadFile} />
{/each}
Expand Down
6 changes: 3 additions & 3 deletions ui/user/src/lib/components/messages/Input.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,9 @@
class="peer
!ml-4
!mr-2
scrollbar-none
w-full resize-none
bg-gray-70 !p-2.5 outline-none dark:bg-gray-950"
w-full
resize-none bg-gray-70
!p-2.5 outline-none scrollbar-none dark:bg-gray-950"
{placeholder}
></textarea>
<button
Expand Down
4 changes: 3 additions & 1 deletion ui/user/src/lib/components/messages/Message.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,9 @@
{#if msg.oauthURL}
{@render oauth()}
{:else if content}
{@render messageContent()}
{#if msg.sourceName !== 'Abort Current Task'}
{@render messageContent()}
{/if}
{:else if msg.toolCall}
{@render toolContent()}
{/if}
Expand Down
17 changes: 2 additions & 15 deletions ui/user/src/lib/components/navbar/Tools.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,14 @@
import { tools, version } from '$lib/stores';
import { currentAssistant } from '$lib/stores';
import { ChatService, EditorService } from '$lib/services';
import { newTool } from '$lib/components/tool/Tool.svelte';
import Menu from '$lib/components/navbar/Menu.svelte';
import { PenBox } from 'lucide-svelte';
let menu = $state<ReturnType<typeof Menu>>();
async function addTool() {
const tool = await ChatService.createTool($currentAssistant.id, {
id: '',
params: {
msg: 'A message to be echoed'
},
toolType: 'javascript',
instructions: `
// Arguments to the tool are available as env vars in CAPITAL_CASE form
// Output for the tool is just the content on stdout (or console.log)
console.log(\`Your message \${process.env.MSG}\`);
`
});
const tool = await ChatService.createTool($currentAssistant.id, newTool);
await EditorService.load($currentAssistant.id, tool.id);
menu?.open.set(false);
}
Expand Down
Loading

0 comments on commit 4db3511

Please sign in to comment.