diff --git a/datasets.go b/datasets.go index 45b665b..c053a26 100644 --- a/datasets.go +++ b/datasets.go @@ -1,5 +1,12 @@ package gptscript +import ( + "context" + "encoding/json" + "fmt" + "os" +) + type DatasetElementMeta struct { Name string `json:"name"` Description string `json:"description"` @@ -48,3 +55,146 @@ type getDatasetElementArgs struct { DatasetID string `json:"datasetID"` Element string `json:"element"` } + +func (g *GPTScript) ListDatasets(ctx context.Context, workspace string) ([]DatasetMeta, error) { + if workspace == "" { + workspace = os.Getenv("GPTSCRIPT_WORKSPACE_DIR") + } + + out, err := g.runBasicCommand(ctx, "datasets", datasetRequest{ + Input: "{}", + Workspace: workspace, + DatasetToolRepo: g.globalOpts.DatasetToolRepo, + }) + if err != nil { + return nil, err + } + + var datasets []DatasetMeta + if err = json.Unmarshal([]byte(out), &datasets); err != nil { + return nil, err + } + return datasets, nil +} + +func (g *GPTScript) CreateDataset(ctx context.Context, workspace, name, description string) (Dataset, error) { + if workspace == "" { + workspace = os.Getenv("GPTSCRIPT_WORKSPACE_DIR") + } + + args := createDatasetArgs{ + Name: name, + Description: description, + } + argsJSON, err := json.Marshal(args) + if err != nil { + return Dataset{}, fmt.Errorf("failed to marshal dataset args: %w", err) + } + + out, err := g.runBasicCommand(ctx, "datasets/create", datasetRequest{ + Input: string(argsJSON), + Workspace: workspace, + DatasetToolRepo: g.globalOpts.DatasetToolRepo, + }) + if err != nil { + return Dataset{}, err + } + + var dataset Dataset + if err = json.Unmarshal([]byte(out), &dataset); err != nil { + return Dataset{}, err + } + return dataset, nil +} + +func (g *GPTScript) AddDatasetElement(ctx context.Context, workspace, datasetID, elementName, elementDescription, elementContent string) (DatasetElementMeta, error) { + if workspace == "" { + workspace = os.Getenv("GPTSCRIPT_WORKSPACE_DIR") + } + + args := addDatasetElementArgs{ + DatasetID: datasetID, + ElementName: elementName, + ElementDescription: elementDescription, + ElementContent: elementContent, + } + argsJSON, err := json.Marshal(args) + if err != nil { + return DatasetElementMeta{}, fmt.Errorf("failed to marshal element args: %w", err) + } + + out, err := g.runBasicCommand(ctx, "datasets/add-element", datasetRequest{ + Input: string(argsJSON), + Workspace: workspace, + DatasetToolRepo: g.globalOpts.DatasetToolRepo, + }) + if err != nil { + return DatasetElementMeta{}, err + } + + var element DatasetElementMeta + if err = json.Unmarshal([]byte(out), &element); err != nil { + return DatasetElementMeta{}, err + } + return element, nil +} + +func (g *GPTScript) ListDatasetElements(ctx context.Context, workspace, datasetID string) ([]DatasetElementMeta, error) { + if workspace == "" { + workspace = os.Getenv("GPTSCRIPT_WORKSPACE_DIR") + } + + args := listDatasetElementArgs{ + DatasetID: datasetID, + } + argsJSON, err := json.Marshal(args) + if err != nil { + return nil, fmt.Errorf("failed to marshal element args: %w", err) + } + + out, err := g.runBasicCommand(ctx, "datasets/list-elements", datasetRequest{ + Input: string(argsJSON), + Workspace: workspace, + DatasetToolRepo: g.globalOpts.DatasetToolRepo, + }) + if err != nil { + return nil, err + } + + var elements []DatasetElementMeta + if err = json.Unmarshal([]byte(out), &elements); err != nil { + return nil, err + } + return elements, nil +} + +func (g *GPTScript) GetDatasetElement(ctx context.Context, workspace, datasetID, elementName string) (DatasetElement, error) { + if workspace == "" { + workspace = os.Getenv("GPTSCRIPT_WORKSPACE_DIR") + } + + args := getDatasetElementArgs{ + DatasetID: datasetID, + Element: elementName, + } + argsJSON, err := json.Marshal(args) + if err != nil { + return DatasetElement{}, fmt.Errorf("failed to marshal element args: %w", err) + } + + out, err := g.runBasicCommand(ctx, "datasets/get-element", datasetRequest{ + Input: string(argsJSON), + Workspace: workspace, + DatasetToolRepo: g.globalOpts.DatasetToolRepo, + }) + if err != nil { + return DatasetElement{}, err + } + + var element DatasetElement + if err = json.Unmarshal([]byte(out), &element); err != nil { + return DatasetElement{}, err + } + + return element, nil +} diff --git a/datasets_test.go b/datasets_test.go new file mode 100644 index 0000000..3763982 --- /dev/null +++ b/datasets_test.go @@ -0,0 +1,52 @@ +package gptscript + +import ( + "context" + "os" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestDatasets(t *testing.T) { + workspace, err := os.MkdirTemp("", "go-gptscript-test") + require.NoError(t, err) + defer func() { + _ = os.RemoveAll(workspace) + }() + + // Create a dataset + dataset, err := g.CreateDataset(context.Background(), workspace, "test-dataset", "This is a test dataset") + require.NoError(t, err) + require.Equal(t, "test-dataset", dataset.Name) + require.Equal(t, "This is a test dataset", dataset.Description) + require.Equal(t, 0, len(dataset.Elements)) + + // Add an element + elementMeta, err := g.AddDatasetElement(context.Background(), workspace, dataset.ID, "test-element", "This is a test element", "This is the content") + require.NoError(t, err) + require.Equal(t, "test-element", elementMeta.Name) + require.Equal(t, "This is a test element", elementMeta.Description) + + // Get the element + element, err := g.GetDatasetElement(context.Background(), workspace, dataset.ID, "test-element") + require.NoError(t, err) + require.Equal(t, "test-element", element.Name) + require.Equal(t, "This is a test element", element.Description) + require.Equal(t, "This is the content", element.Contents) + + // List elements in the dataset + elements, err := g.ListDatasetElements(context.Background(), workspace, dataset.ID) + require.NoError(t, err) + require.Equal(t, 1, len(elements)) + require.Equal(t, "test-element", elements[0].Name) + require.Equal(t, "This is a test element", elements[0].Description) + + // List datasets + datasets, err := g.ListDatasets(context.Background(), workspace) + require.NoError(t, err) + require.Equal(t, 1, len(datasets)) + require.Equal(t, "test-dataset", datasets[0].Name) + require.Equal(t, "This is a test dataset", datasets[0].Description) + require.Equal(t, dataset.ID, datasets[0].ID) +} diff --git a/gptscript.go b/gptscript.go index 6178c67..1e30d95 100644 --- a/gptscript.go +++ b/gptscript.go @@ -7,7 +7,6 @@ import ( "context" "encoding/base64" "encoding/json" - "errors" "fmt" "io" "log/slog" @@ -389,176 +388,6 @@ func (g *GPTScript) DeleteCredential(ctx context.Context, credCtx, name string) return err } -// Dataset methods - -func (g *GPTScript) ListDatasets(ctx context.Context, workspace string) ([]DatasetMeta, error) { - if workspace == "" { - workspace = os.Getenv("GPTSCRIPT_WORKSPACE_DIR") - } - - out, err := g.runBasicCommand(ctx, "datasets", datasetRequest{ - Input: "{}", - Workspace: workspace, - DatasetToolRepo: g.globalOpts.DatasetToolRepo, - }) - - if err != nil { - return nil, err - } - - if strings.HasPrefix(out, "ERROR:") { - return nil, errors.New(out) - } - - var datasets []DatasetMeta - if err = json.Unmarshal([]byte(out), &datasets); err != nil { - return nil, err - } - return datasets, nil -} - -func (g *GPTScript) CreateDataset(ctx context.Context, workspace, name, description string) (Dataset, error) { - if workspace == "" { - workspace = os.Getenv("GPTSCRIPT_WORKSPACE_DIR") - } - - args := createDatasetArgs{ - Name: name, - Description: description, - } - argsJSON, err := json.Marshal(args) - if err != nil { - return Dataset{}, fmt.Errorf("failed to marshal dataset args: %w", err) - } - - out, err := g.runBasicCommand(ctx, "datasets/create", datasetRequest{ - Input: string(argsJSON), - Workspace: workspace, - DatasetToolRepo: g.globalOpts.DatasetToolRepo, - }) - - if err != nil { - return Dataset{}, err - } - - if strings.HasPrefix(out, "ERROR:") { - return Dataset{}, errors.New(out) - } - - var dataset Dataset - if err = json.Unmarshal([]byte(out), &dataset); err != nil { - return Dataset{}, err - } - return dataset, nil -} - -func (g *GPTScript) AddDatasetElement(ctx context.Context, workspace, datasetID, elementName, elementDescription, elementContent string) (DatasetElementMeta, error) { - if workspace == "" { - workspace = os.Getenv("GPTSCRIPT_WORKSPACE_DIR") - } - - args := addDatasetElementArgs{ - DatasetID: datasetID, - ElementName: elementName, - ElementDescription: elementDescription, - ElementContent: elementContent, - } - argsJSON, err := json.Marshal(args) - if err != nil { - return DatasetElementMeta{}, fmt.Errorf("failed to marshal element args: %w", err) - } - - out, err := g.runBasicCommand(ctx, "datasets/add-element", datasetRequest{ - Input: string(argsJSON), - Workspace: workspace, - DatasetToolRepo: g.globalOpts.DatasetToolRepo, - }) - - if err != nil { - return DatasetElementMeta{}, err - } - - if strings.HasPrefix(out, "ERROR:") { - return DatasetElementMeta{}, errors.New(out) - } - - var element DatasetElementMeta - if err = json.Unmarshal([]byte(out), &element); err != nil { - return DatasetElementMeta{}, err - } - return element, nil -} - -func (g *GPTScript) ListDatasetElements(ctx context.Context, workspace, datasetID string) ([]DatasetElementMeta, error) { - if workspace == "" { - workspace = os.Getenv("GPTSCRIPT_WORKSPACE_DIR") - } - - args := listDatasetElementArgs{ - DatasetID: datasetID, - } - argsJSON, err := json.Marshal(args) - if err != nil { - return nil, fmt.Errorf("failed to marshal element args: %w", err) - } - - out, err := g.runBasicCommand(ctx, "datasets/list-elements", datasetRequest{ - Input: string(argsJSON), - Workspace: workspace, - DatasetToolRepo: g.globalOpts.DatasetToolRepo, - }) - - if err != nil { - return nil, err - } - - if strings.HasPrefix(out, "ERROR:") { - return nil, errors.New(out) - } - - var elements []DatasetElementMeta - if err = json.Unmarshal([]byte(out), &elements); err != nil { - return nil, err - } - return elements, nil -} - -func (g *GPTScript) GetDatasetElement(ctx context.Context, workspace, datasetID, elementName string) (DatasetElement, error) { - if workspace == "" { - workspace = os.Getenv("GPTSCRIPT_WORKSPACE_DIR") - } - - args := getDatasetElementArgs{ - DatasetID: datasetID, - Element: elementName, - } - argsJSON, err := json.Marshal(args) - if err != nil { - return DatasetElement{}, fmt.Errorf("failed to marshal element args: %w", err) - } - - out, err := g.runBasicCommand(ctx, "datasets/get-element", datasetRequest{ - Input: string(argsJSON), - Workspace: workspace, - DatasetToolRepo: g.globalOpts.DatasetToolRepo, - }) - - if err != nil { - return DatasetElement{}, err - } - - if strings.HasPrefix(out, "ERROR:") { - return DatasetElement{}, errors.New(out) - } - - var element DatasetElement - if err = json.Unmarshal([]byte(out), &element); err != nil { - return DatasetElement{}, err - } - - return element, nil -} - func (g *GPTScript) runBasicCommand(ctx context.Context, requestPath string, body any) (string, error) { run := &Run{ url: g.globalOpts.URL, diff --git a/gptscript_test.go b/gptscript_test.go index 82bf735..32adff9 100644 --- a/gptscript_test.go +++ b/gptscript_test.go @@ -1560,46 +1560,3 @@ func TestCredentials(t *testing.T) { require.Error(t, err) require.True(t, errors.As(err, &ErrNotFound{})) } - -func TestDatasets(t *testing.T) { - workspace, err := os.MkdirTemp("", "go-gptscript-test") - require.NoError(t, err) - defer func() { - _ = os.RemoveAll(workspace) - }() - - // Create a dataset - dataset, err := g.CreateDataset(context.Background(), workspace, "test-dataset", "This is a test dataset") - require.NoError(t, err) - require.Equal(t, "test-dataset", dataset.Name) - require.Equal(t, "This is a test dataset", dataset.Description) - require.Equal(t, 0, len(dataset.Elements)) - - // Add an element - elementMeta, err := g.AddDatasetElement(context.Background(), workspace, dataset.ID, "test-element", "This is a test element", "This is the content") - require.NoError(t, err) - require.Equal(t, "test-element", elementMeta.Name) - require.Equal(t, "This is a test element", elementMeta.Description) - - // Get the element - element, err := g.GetDatasetElement(context.Background(), workspace, dataset.ID, "test-element") - require.NoError(t, err) - require.Equal(t, "test-element", element.Name) - require.Equal(t, "This is a test element", element.Description) - require.Equal(t, "This is the content", element.Contents) - - // List elements in the dataset - elements, err := g.ListDatasetElements(context.Background(), workspace, dataset.ID) - require.NoError(t, err) - require.Equal(t, 1, len(elements)) - require.Equal(t, "test-element", elements[0].Name) - require.Equal(t, "This is a test element", elements[0].Description) - - // List datasets - datasets, err := g.ListDatasets(context.Background(), workspace) - require.NoError(t, err) - require.Equal(t, 1, len(datasets)) - require.Equal(t, "test-dataset", datasets[0].Name) - require.Equal(t, "This is a test dataset", datasets[0].Description) - require.Equal(t, dataset.ID, datasets[0].ID) -} diff --git a/opts.go b/opts.go index 283b4ec..6c9e1ab 100644 --- a/opts.go +++ b/opts.go @@ -12,6 +12,7 @@ type GlobalOptions struct { CacheDir string `json:"CacheDir"` Env []string `json:"env"` DatasetToolRepo string `json:"DatasetToolRepo"` + WorkspaceTool string `json:"WorkspaceTool"` } func (g GlobalOptions) toEnv() []string { diff --git a/workspace.go b/workspace.go new file mode 100644 index 0000000..86b8c2e --- /dev/null +++ b/workspace.go @@ -0,0 +1,189 @@ +package gptscript + +import ( + "context" + "encoding/base64" + "encoding/json" + "strings" +) + +func (g *GPTScript) CreateWorkspace(ctx context.Context, providerType string) (string, error) { + out, err := g.runBasicCommand(ctx, "workspaces/create", map[string]any{ + "provider": providerType, + "workspaceTool": g.globalOpts.WorkspaceTool, + }) + if err != nil { + return "", err + } + + return strings.TrimSpace(out), nil +} + +type DeleteWorkspaceOptions struct { + IgnoreNotFound bool +} + +func (g *GPTScript) DeleteWorkspace(ctx context.Context, workspaceID string, opts ...DeleteWorkspaceOptions) error { + var opt DeleteWorkspaceOptions + for _, o := range opts { + opt.IgnoreNotFound = opt.IgnoreNotFound || o.IgnoreNotFound + } + _, err := g.runBasicCommand(ctx, "workspaces/delete", map[string]any{ + "id": workspaceID, + "ignoreNotFound": opt.IgnoreNotFound, + "workspaceTool": g.globalOpts.WorkspaceTool, + }) + + return err +} + +type CreateDirectoryInWorkspaceOptions struct { + IgnoreExists bool +} + +func (g *GPTScript) CreateDirectoryInWorkspace(ctx context.Context, workspaceID, dir string, opts ...CreateDirectoryInWorkspaceOptions) error { + var opt CreateDirectoryInWorkspaceOptions + for _, o := range opts { + opt.IgnoreExists = opt.IgnoreExists || o.IgnoreExists + } + + _, err := g.runBasicCommand(ctx, "workspaces/mkdir", map[string]any{ + "id": workspaceID, + "directoryName": dir, + "ignoreExists": opt.IgnoreExists, + "workspaceTool": g.globalOpts.WorkspaceTool, + }) + + return err +} + +type DeleteDirectoryInWorkspaceOptions struct { + IgnoreNotFound bool + MustBeEmpty bool +} + +func (g *GPTScript) DeleteDirectoryInWorkspace(ctx context.Context, workspaceID, dir string, opts ...DeleteDirectoryInWorkspaceOptions) error { + var opt DeleteDirectoryInWorkspaceOptions + for _, o := range opts { + o.IgnoreNotFound = opt.IgnoreNotFound || o.IgnoreNotFound + o.MustBeEmpty = opt.MustBeEmpty || o.MustBeEmpty + } + + _, err := g.runBasicCommand(ctx, "workspaces/rmdir", map[string]any{ + "id": workspaceID, + "directoryName": dir, + "ignoreNotFound": opt.IgnoreNotFound, + "mustBeEmpty": opt.MustBeEmpty, + "workspaceTool": g.globalOpts.WorkspaceTool, + }) + + return err +} + +type ListFilesInWorkspaceOptions struct { + SubDir string + NonRecursive bool + ExcludeHidden bool +} + +type WorkspaceContent struct { + ID, Path, FileName string + Children []WorkspaceContent +} + +func (g *GPTScript) ListFilesInWorkspace(ctx context.Context, workspaceID string, opts ...ListFilesInWorkspaceOptions) (*WorkspaceContent, error) { + var opt ListFilesInWorkspaceOptions + for _, o := range opts { + if o.SubDir != "" { + opt.SubDir = o.SubDir + } + opt.NonRecursive = opt.NonRecursive || o.NonRecursive + opt.ExcludeHidden = opt.ExcludeHidden || o.ExcludeHidden + } + + out, err := g.runBasicCommand(ctx, "workspaces/list", map[string]any{ + "id": workspaceID, + "subDir": opt.SubDir, + "excludeHidden": opt.ExcludeHidden, + "nonRecursive": opt.NonRecursive, + "workspaceTool": g.globalOpts.WorkspaceTool, + "json": true, + }) + if err != nil { + return nil, err + } + + var content []WorkspaceContent + err = json.Unmarshal([]byte(out), &content) + if err != nil { + return nil, err + } + + if len(content) == 0 { + return &WorkspaceContent{ID: workspaceID}, nil + } + + return &content[0], nil +} + +type CreateFileInWorkspaceOptions struct { + MustNotExist bool + WithoutCreate bool + CreateDirs bool +} + +func (g *GPTScript) WriteFileInWorkspace(ctx context.Context, workspaceID, filePath string, contents []byte, opts ...CreateFileInWorkspaceOptions) error { + var opt CreateFileInWorkspaceOptions + for _, o := range opts { + opt.MustNotExist = opt.MustNotExist || o.MustNotExist + opt.WithoutCreate = opt.WithoutCreate || o.WithoutCreate + opt.CreateDirs = opt.CreateDirs || o.CreateDirs + } + + _, err := g.runBasicCommand(ctx, "workspaces/write-file", map[string]any{ + "id": workspaceID, + "contents": base64.StdEncoding.EncodeToString(contents), + "filePath": filePath, + "mustNotExist": opt.MustNotExist, + "withoutCreate": opt.WithoutCreate, + "createDirs": opt.CreateDirs, + "workspaceTool": g.globalOpts.WorkspaceTool, + "base64EncodedInput": true, + }) + + return err +} + +type DeleteFileInWorkspaceOptions struct { + IgnoreNotFound bool +} + +func (g *GPTScript) DeleteFileInWorkspace(ctx context.Context, workspaceID, filePath string, opts ...DeleteFileInWorkspaceOptions) error { + var opt DeleteFileInWorkspaceOptions + for _, o := range opts { + opt.IgnoreNotFound = opt.IgnoreNotFound || o.IgnoreNotFound + } + + _, err := g.runBasicCommand(ctx, "workspaces/delete-file", map[string]any{ + "id": workspaceID, + "filePath": filePath, + "ignoreNotFound": opt.IgnoreNotFound, + "workspaceTool": g.globalOpts.WorkspaceTool, + }) + + return err +} + +func (g *GPTScript) ReadFileInWorkspace(ctx context.Context, workspaceID, filePath string) ([]byte, error) { + out, err := g.runBasicCommand(ctx, "workspaces/read-file", map[string]any{ + "id": workspaceID, + "filePath": filePath, + "workspaceTool": g.globalOpts.WorkspaceTool, + "base64EncodeOutput": true, + }) + if err != nil { + return nil, err + } + + return base64.StdEncoding.DecodeString(out) +} diff --git a/workspace_test.go b/workspace_test.go new file mode 100644 index 0000000..cba683f --- /dev/null +++ b/workspace_test.go @@ -0,0 +1,172 @@ +package gptscript + +import ( + "bytes" + "context" + "testing" +) + +func TestCreateAndDeleteWorkspace(t *testing.T) { + id, err := g.CreateWorkspace(context.Background(), "directory") + if err != nil { + t.Fatalf("Error creating workspace: %v", err) + } + + err = g.DeleteWorkspace(context.Background(), id) + if err != nil { + t.Errorf("Error deleting workspace: %v", err) + } +} + +func TestCreateDirectory(t *testing.T) { + id, err := g.CreateWorkspace(context.Background(), "directory") + if err != nil { + t.Fatalf("Error creating workspace: %v", err) + } + + t.Cleanup(func() { + err := g.DeleteWorkspace(context.Background(), id) + if err != nil { + t.Errorf("Error deleting workspace: %v", err) + } + }) + + err = g.CreateDirectoryInWorkspace(context.Background(), id, "test") + if err != nil { + t.Fatalf("Error creating directory: %v", err) + } + + err = g.DeleteDirectoryInWorkspace(context.Background(), id, "test") + if err != nil { + t.Errorf("Error listing files: %v", err) + } +} + +func TestWriteReadAndDeleteFileFromWorkspace(t *testing.T) { + id, err := g.CreateWorkspace(context.Background(), "directory") + if err != nil { + t.Fatalf("Error creating workspace: %v", err) + } + + t.Cleanup(func() { + err := g.DeleteWorkspace(context.Background(), id) + if err != nil { + t.Errorf("Error deleting workspace: %v", err) + } + }) + + err = g.WriteFileInWorkspace(context.Background(), id, "test.txt", []byte("test")) + if err != nil { + t.Fatalf("Error creating file: %v", err) + } + + content, err := g.ReadFileInWorkspace(context.Background(), id, "test.txt") + if err != nil { + t.Errorf("Error reading file: %v", err) + } + + if !bytes.Equal(content, []byte("test")) { + t.Errorf("Unexpected content: %s", content) + } + + err = g.DeleteFileInWorkspace(context.Background(), id, "test.txt") + if err != nil { + t.Errorf("Error deleting file: %v", err) + } +} + +func TestLsComplexWorkspace(t *testing.T) { + id, err := g.CreateWorkspace(context.Background(), "directory") + if err != nil { + t.Fatalf("Error creating workspace: %v", err) + } + + t.Cleanup(func() { + err := g.DeleteWorkspace(context.Background(), id) + if err != nil { + t.Errorf("Error deleting workspace: %v", err) + } + }) + + err = g.CreateDirectoryInWorkspace(context.Background(), id, "test") + if err != nil { + t.Fatalf("Error creating directory: %v", err) + } + + err = g.WriteFileInWorkspace(context.Background(), id, "test/test1.txt", []byte("hello1")) + if err != nil { + t.Fatalf("Error creating file: %v", err) + } + + err = g.WriteFileInWorkspace(context.Background(), id, "test1/test2.txt", []byte("hello2"), CreateFileInWorkspaceOptions{CreateDirs: true}) + if err != nil { + t.Fatalf("Error creating file: %v", err) + } + + err = g.WriteFileInWorkspace(context.Background(), id, "test1/test2.txt", []byte("hello-2"), CreateFileInWorkspaceOptions{MustNotExist: true}) + if err == nil { + t.Fatalf("Expected error creating file that must not exist") + } + + err = g.WriteFileInWorkspace(context.Background(), id, "test1/test3.txt", []byte("hello3"), CreateFileInWorkspaceOptions{WithoutCreate: true}) + if err == nil { + t.Fatalf("Expected error creating file that doesn't exist") + } + + err = g.WriteFileInWorkspace(context.Background(), id, ".hidden.txt", []byte("hidden")) + if err != nil { + t.Fatalf("Error creating hidden file: %v", err) + } + + // List all files + content, err := g.ListFilesInWorkspace(context.Background(), id) + if err != nil { + t.Fatalf("Error listing files: %v", err) + } + + if content.ID != id { + t.Errorf("Unexpected ID: %s", content.ID) + } + + if content.Path != "" { + t.Errorf("Unexpected path: %s", content.Path) + } + + if content.FileName != "" { + t.Errorf("Unexpected filename: %s", content.FileName) + } + + if len(content.Children) != 3 { + t.Errorf("Unexpected number of files: %d", len(content.Children)) + } + + // List files in subdirectory + content, err = g.ListFilesInWorkspace(context.Background(), id, ListFilesInWorkspaceOptions{SubDir: "test1"}) + if err != nil { + t.Fatalf("Error listing files: %v", err) + } + + if len(content.Children) != 1 { + t.Errorf("Unexpected number of files: %d", len(content.Children)) + } + + // Exclude hidden files + content, err = g.ListFilesInWorkspace(context.Background(), id, ListFilesInWorkspaceOptions{ExcludeHidden: true}) + if err != nil { + t.Fatalf("Error listing files: %v", err) + } + + if len(content.Children) != 2 { + t.Errorf("Unexpected number of files when listing without hidden: %d", len(content.Children)) + } + + // List non-recursive + content, err = g.ListFilesInWorkspace(context.Background(), id, ListFilesInWorkspaceOptions{NonRecursive: true}) + if err != nil { + t.Fatalf("Error listing files: %v", err) + } + + if len(content.Children) != 1 { + t.Errorf("Unexpected number of files when listing non-recursive: %d", len(content.Children)) + } +}