From c3a3279b0c2ca5d22c8aebb4b35761de2797af6b Mon Sep 17 00:00:00 2001 From: Donnie Adams Date: Thu, 17 Oct 2024 15:19:44 -0400 Subject: [PATCH] feat: simplify the workspace API and add support for s3 (#878) Signed-off-by: Donnie Adams --- pkg/sdkserver/routes.go | 3 +- pkg/sdkserver/workspaces.go | 94 ++++++++++--------------------------- 2 files changed, 25 insertions(+), 72 deletions(-) diff --git a/pkg/sdkserver/routes.go b/pkg/sdkserver/routes.go index 894823b3..4d4ceb2e 100644 --- a/pkg/sdkserver/routes.go +++ b/pkg/sdkserver/routes.go @@ -76,8 +76,7 @@ func (s *server) addRoutes(mux *http.ServeMux) { mux.HandleFunc("POST /workspaces/create", s.createWorkspace) mux.HandleFunc("POST /workspaces/delete", s.deleteWorkspace) mux.HandleFunc("POST /workspaces/list", s.listWorkspaceContents) - mux.HandleFunc("POST /workspaces/mkdir", s.mkDirInWorkspace) - mux.HandleFunc("POST /workspaces/rmdir", s.rmDirInWorkspace) + mux.HandleFunc("POST /workspaces/remove-all-with-prefix", s.removeAllWithPrefixInWorkspace) mux.HandleFunc("POST /workspaces/write-file", s.writeFileInWorkspace) mux.HandleFunc("POST /workspaces/delete-file", s.removeFileInWorkspace) mux.HandleFunc("POST /workspaces/read-file", s.readFileInWorkspace) diff --git a/pkg/sdkserver/workspaces.go b/pkg/sdkserver/workspaces.go index ef73b347..87bc4583 100644 --- a/pkg/sdkserver/workspaces.go +++ b/pkg/sdkserver/workspaces.go @@ -11,8 +11,9 @@ import ( ) type workspaceCommonRequest struct { - ID string `json:"id"` - WorkspaceTool string `json:"workspaceTool"` + ID string `json:"id"` + WorkspaceTool string `json:"workspaceTool"` + Env []string `json:"env"` } func (w workspaceCommonRequest) getToolRepo() string { @@ -50,7 +51,7 @@ func (s *server) createWorkspace(w http.ResponseWriter, r *http.Request) { out, err := s.client.Run( r.Context(), prg, - s.gptscriptOpts.Env, + reqObject.Env, fmt.Sprintf( `{"provider": "%s", "data_home": "%s", "workspace_ids": "%s"}`, reqObject.ProviderType, reqObject.DirectoryDataHome, strings.Join(reqObject.FromWorkspaceIDs, ","), @@ -85,7 +86,7 @@ func (s *server) deleteWorkspace(w http.ResponseWriter, r *http.Request) { out, err := s.client.Run( r.Context(), prg, - s.gptscriptOpts.Env, + reqObject.Env, fmt.Sprintf( `{"workspace_id": "%s"}`, reqObject.ID, @@ -102,10 +103,7 @@ func (s *server) deleteWorkspace(w http.ResponseWriter, r *http.Request) { type listWorkspaceContentsRequest struct { workspaceCommonRequest `json:",inline"` ID string `json:"id"` - SubDir string `json:"subDir"` - NonRecursive bool `json:"nonRecursive"` - ExcludeHidden bool `json:"excludeHidden"` - JSON bool `json:"json"` + Prefix string `json:"prefix"` } func (s *server) listWorkspaceContents(w http.ResponseWriter, r *http.Request) { @@ -125,10 +123,10 @@ func (s *server) listWorkspaceContents(w http.ResponseWriter, r *http.Request) { out, err := s.client.Run( r.Context(), prg, - s.gptscriptOpts.Env, + reqObject.Env, fmt.Sprintf( - `{"workspace_id": "%s", "ls_sub_dir": "%s", "ls_non_recursive": %t, "ls_exclude_hidden": %t, "ls_json": %t}`, - reqObject.ID, reqObject.SubDir, reqObject.NonRecursive, reqObject.ExcludeHidden, reqObject.JSON, + `{"workspace_id": "%s", "ls_prefix": "%s"}`, + reqObject.ID, reqObject.Prefix, ), ) if err != nil { @@ -139,22 +137,20 @@ func (s *server) listWorkspaceContents(w http.ResponseWriter, r *http.Request) { writeResponse(logger, w, map[string]any{"stdout": out}) } -type mkDirRequest struct { +type removeAllWithPrefixInWorkspaceRequest struct { workspaceCommonRequest `json:",inline"` - DirectoryName string `json:"directoryName"` - IgnoreExists bool `json:"ignoreExists"` - CreateDirs bool `json:"createDirs"` + Prefix string `json:"prefix"` } -func (s *server) mkDirInWorkspace(w http.ResponseWriter, r *http.Request) { +func (s *server) removeAllWithPrefixInWorkspace(w http.ResponseWriter, r *http.Request) { logger := gcontext.GetLogger(r.Context()) - var reqObject mkDirRequest + var reqObject removeAllWithPrefixInWorkspaceRequest if err := json.NewDecoder(r.Body).Decode(&reqObject); err != nil { writeError(logger, w, http.StatusBadRequest, fmt.Errorf("invalid request body: %w", err)) return } - prg, err := loader.Program(r.Context(), reqObject.getToolRepo(), "Create Directory In Workspace", loader.Options{Cache: s.client.Cache}) + prg, err := loader.Program(r.Context(), reqObject.getToolRepo(), "Remove All With Prefix In Workspace", loader.Options{Cache: s.client.Cache}) if err != nil { writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to load program: %w", err)) return @@ -163,48 +159,10 @@ func (s *server) mkDirInWorkspace(w http.ResponseWriter, r *http.Request) { out, err := s.client.Run( r.Context(), prg, - s.gptscriptOpts.Env, + reqObject.Env, fmt.Sprintf( - `{"workspace_id": "%s", "directory_name": "%s", "mk_dir_ignore_exists": %t, "mk_dir_create_dirs": %t}`, - reqObject.ID, reqObject.DirectoryName, reqObject.IgnoreExists, reqObject.CreateDirs, - ), - ) - if err != nil { - writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to run program: %w", err)) - return - } - - writeResponse(logger, w, map[string]any{"stdout": out}) -} - -type rmDirRequest struct { - workspaceCommonRequest `json:",inline"` - DirectoryName string `json:"directoryName"` - IgnoreNotFound bool `json:"ignoreNotFound"` - MustBeEmpty bool `json:"mustBeEmpty"` -} - -func (s *server) rmDirInWorkspace(w http.ResponseWriter, r *http.Request) { - logger := gcontext.GetLogger(r.Context()) - var reqObject rmDirRequest - if err := json.NewDecoder(r.Body).Decode(&reqObject); err != nil { - writeError(logger, w, http.StatusBadRequest, fmt.Errorf("invalid request body: %w", err)) - return - } - - prg, err := loader.Program(r.Context(), reqObject.getToolRepo(), "Remove Directory In Workspace", loader.Options{Cache: s.client.Cache}) - if err != nil { - writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to load program: %w", err)) - return - } - - out, err := s.client.Run( - r.Context(), - prg, - s.gptscriptOpts.Env, - fmt.Sprintf( - `{"workspace_id": "%s", "directory_name": "%s", "ignore_not_found": %t, "rm_dir_must_be_empty": %t}`, - reqObject.ID, reqObject.DirectoryName, reqObject.IgnoreNotFound, reqObject.MustBeEmpty, + `{"workspace_id": "%s", "prefix": "%s"}`, + reqObject.ID, reqObject.Prefix, ), ) if err != nil { @@ -220,9 +178,6 @@ type writeFileInWorkspaceRequest struct { FilePath string `json:"filePath"` Contents string `json:"contents"` Base64EncodedInput bool `json:"base64EncodedInput"` - MustNotExist bool `json:"mustNotExist"` - CreateDirs bool `json:"createDirs"` - WithoutCreate bool `json:"withoutCreate"` } func (s *server) writeFileInWorkspace(w http.ResponseWriter, r *http.Request) { @@ -242,10 +197,10 @@ func (s *server) writeFileInWorkspace(w http.ResponseWriter, r *http.Request) { out, err := s.client.Run( r.Context(), prg, - s.gptscriptOpts.Env, + reqObject.Env, fmt.Sprintf( - `{"workspace_id": "%s", "file_path": "%s", "file_contents": "%s", "write_file_must_not_exist": %t, "write_file_create_dirs": %t, "write_file_without_create": %t, "write_file_base64_encoded_input": %t}`, - reqObject.ID, reqObject.FilePath, reqObject.Contents, reqObject.MustNotExist, reqObject.CreateDirs, reqObject.WithoutCreate, reqObject.Base64EncodedInput, + `{"workspace_id": "%s", "file_path": "%s", "file_contents": "%s", "write_file_base64_encoded_input": %t}`, + reqObject.ID, reqObject.FilePath, reqObject.Contents, reqObject.Base64EncodedInput, ), ) if err != nil { @@ -259,7 +214,6 @@ func (s *server) writeFileInWorkspace(w http.ResponseWriter, r *http.Request) { type rmFileInWorkspaceRequest struct { workspaceCommonRequest `json:",inline"` FilePath string `json:"filePath"` - IgnoreNotFound bool `json:"ignoreNotFound"` } func (s *server) removeFileInWorkspace(w http.ResponseWriter, r *http.Request) { @@ -279,10 +233,10 @@ func (s *server) removeFileInWorkspace(w http.ResponseWriter, r *http.Request) { out, err := s.client.Run( r.Context(), prg, - s.gptscriptOpts.Env, + reqObject.Env, fmt.Sprintf( - `{"workspace_id": "%s", "file_path": "%s", "ignore_not_found": %t}`, - reqObject.ID, reqObject.FilePath, reqObject.IgnoreNotFound, + `{"workspace_id": "%s", "file_path": "%s"}`, + reqObject.ID, reqObject.FilePath, ), ) if err != nil { @@ -316,7 +270,7 @@ func (s *server) readFileInWorkspace(w http.ResponseWriter, r *http.Request) { out, err := s.client.Run( r.Context(), prg, - s.gptscriptOpts.Env, + reqObject.Env, fmt.Sprintf( `{"workspace_id": "%s", "file_path": "%s", "read_file_base64_encode_output": %t}`, reqObject.ID, reqObject.FilePath, reqObject.Base64EncodeOutput,