Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: enhancements for otto8 #1334

Merged
merged 1 commit into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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