diff --git a/internal/api/client.gen.go b/internal/api/client.gen.go index 32d9ae1..38f088d 100644 --- a/internal/api/client.gen.go +++ b/internal/api/client.gen.go @@ -657,9 +657,6 @@ type ApiSessionStartRequest struct { // SolveCaptchas Whether to try to automatically solve captchas SolveCaptchas *bool `json:"solve_captchas,omitempty"` - // UseFileStorage Whether FileStorage should be attached to the session. - UseFileStorage *bool `json:"use_file_storage,omitempty"` - // UserAgent The user agent to use for the session UserAgent *string `json:"user_agent,omitempty"` @@ -2483,9 +2480,6 @@ type SessionResponse struct { // Deprecated: this property has been marked as deprecated upstream, but no `x-deprecated-reason` was set TimeoutMinutes *int `json:"timeout_minutes,omitempty"` - // UseFileStorage Whether FileStorage was attached to the session. - UseFileStorage *bool `json:"use_file_storage,omitempty"` - // UserAgent The user agent to use for the session UserAgent *string `json:"user_agent,omitempty"` diff --git a/internal/api/client.go b/internal/api/client.go index e773e21..9127b07 100644 --- a/internal/api/client.go +++ b/internal/api/client.go @@ -4,10 +4,7 @@ import ( "context" "crypto/tls" "fmt" - "io" "net/http" - "net/url" - "strings" "time" notteErrors "github.com/nottelabs/notte-cli/internal/errors" @@ -224,28 +221,6 @@ func (c *NotteClient) APIKey() string { return c.apiKey } -// DownloadUploadedFile requests a temporary download link for a user-uploaded file. -// This endpoint is kept here until it is available in the generated OpenAPI client. -func (c *NotteClient) DownloadUploadedFile(ctx context.Context, filename string) (*http.Response, []byte, error) { - endpoint := strings.TrimRight(c.baseURL, "/") + "/storage/uploads/" + url.PathEscape(filename) - req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint, nil) - if err != nil { - return nil, nil, fmt.Errorf("failed to create uploaded file download request: %w", err) - } - - resp, err := c.httpClient.Do(req) - if err != nil { - return nil, nil, err - } - defer func() { _ = resp.Body.Close() }() - - body, err := io.ReadAll(resp.Body) - if err != nil { - return resp, nil, fmt.Errorf("failed to read uploaded file download response: %w", err) - } - return resp, body, nil -} - // Context helper for commands func DefaultContext() context.Context { return context.Background() diff --git a/internal/cmd/files.go b/internal/cmd/files.go index 1d50843..7161eda 100644 --- a/internal/cmd/files.go +++ b/internal/cmd/files.go @@ -6,21 +6,21 @@ import ( "encoding/json" "fmt" "io" + "mime" "mime/multipart" "net/http" + "net/url" "os" "path/filepath" + "strings" "github.com/spf13/cobra" - - "github.com/nottelabs/notte-cli/internal/api" ) var ( filesListUploadsFlag bool filesListDownloadsFlag bool filesListFrom string - filesDownloadFrom string filesDownloadOutput string ) @@ -32,32 +32,30 @@ const ( var filesCmd = &cobra.Command{ Use: "files", Short: "Manage stored files", - Long: "Upload, list, and download files from notte.cc storage.", + Long: "Upload, list, and download files owned by a browser session.", } var filesListCmd = &cobra.Command{ Use: "list", Short: "List stored files", - Long: `List user-uploaded files or files downloaded by a browser session. -Use --from uploads for user uploads or --from session for session downloads.`, - RunE: runFilesList, + Long: `List all files owned by a browser session. Use --from uploads or --from session to filter the source.`, + RunE: runFilesList, } var filesUploadCmd = &cobra.Command{ Use: "upload ", Short: "Upload a file", - Long: "Upload a file to notte.cc storage.", + Long: "Upload a file to a browser session.", Args: cobra.ExactArgs(1), RunE: runFilesUpload, } var filesDownloadCmd = &cobra.Command{ - Use: "download ", - Short: "Download a file by name", - Long: `Download a user-uploaded file or a file produced by a browser session. -Use --from uploads for user uploads or --from session for session downloads.`, - Args: cobra.ExactArgs(1), - RunE: runFilesDownload, + Use: "download ", + Short: "Download a session file by ID", + Long: "Download a user upload or browser download by its immutable file ID.", + Args: cobra.ExactArgs(1), + RunE: runFilesDownload, } func init() { @@ -69,15 +67,38 @@ func init() { // List command flags filesListCmd.Flags().BoolVar(&filesListUploadsFlag, "uploads", false, "List uploaded files") filesListCmd.Flags().BoolVar(&filesListDownloadsFlag, "downloads", false, "List downloaded files from a session") - filesListCmd.Flags().StringVar(&filesListFrom, "from", "", "File source: uploads or session (default session)") + filesListCmd.Flags().StringVar(&filesListFrom, "from", "", "File source: uploads or session (default all)") filesListCmd.Flags().StringVar(&sessionID, "session-id", "", "Session ID (uses current session if not specified)") _ = filesListCmd.Flags().MarkDeprecated("uploads", "use --from uploads instead") _ = filesListCmd.Flags().MarkDeprecated("downloads", "use --from session instead") // Download command flags filesDownloadCmd.Flags().StringVar(&sessionID, "session-id", "", "Session ID (uses current session if not specified)") - filesDownloadCmd.Flags().StringVar(&filesDownloadFrom, "from", "", "File source: uploads or session (default session)") filesDownloadCmd.Flags().StringVar(&filesDownloadOutput, "path", "", "Output file path (defaults to current directory)") + filesUploadCmd.Flags().StringVar(&sessionID, "session-id", "", "Session ID (uses current session if not specified)") +} + +type sessionFile struct { + ID string `json:"id"` + SessionID string `json:"session_id"` + Filename string `json:"filename"` + MimeType string `json:"mime_type"` + Size int64 `json:"size"` + Checksum string `json:"checksum"` + CreatedAt string `json:"created_at"` + ExpiresAt string `json:"expires_at"` + Source string `json:"source"` +} + +type sessionFilesPage struct { + Files []sessionFile `json:"files"` + Total int `json:"total"` + Limit int `json:"limit"` + Offset int `json:"offset"` +} + +func sessionFilesURL(clientBaseURL, id string) string { + return strings.TrimRight(clientBaseURL, "/") + "/sessions/" + url.PathEscape(sessionID) + "/files" + id } func resolveFilesSource(from string, uploads, downloads bool) (string, error) { @@ -96,7 +117,9 @@ func resolveFilesSource(from string, uploads, downloads bool) (string, error) { } switch from { - case "", filesSourceSession: + case "": + return "", nil + case filesSourceSession: return filesSourceSession, nil case filesSourceUploads: return filesSourceUploads, nil @@ -204,81 +227,47 @@ func runFilesList(cmd *cobra.Command, args []string) error { return err } + if err := RequireSessionID(); err != nil { + return err + } client, err := GetClient() if err != nil { return err } - - formatter := GetFormatter() - + ctx, cancel := GetContextWithTimeout(cmd.Context()) + defer cancel() + endpoint := sessionFilesURL(client.BaseURL(), "") + "?limit=1000" if source == filesSourceUploads { - ctx, cancel := GetContextWithTimeout(cmd.Context()) - defer cancel() - - params := &api.FileListUploadsParams{} - resp, err := client.Client().FileListUploadsWithResponse(ctx, params) - if err != nil { - return fmt.Errorf("API request failed: %w", err) - } - - if err := HandleAPIResponse(resp.HTTPResponse, resp.Body); err != nil { - return err - } - - var fileNames []string - if resp.JSON200 != nil { - for _, f := range resp.JSON200.Files { - fileNames = append(fileNames, f.Name) - } - } - if printed, err := PrintListOrEmpty(fileNames, "No uploaded files."); err != nil { - return err - } else if printed { - return nil - } - - if !IsJSONOutput() { - fmt.Println("Your uploaded files:") - } - return formatter.Print(fileNames) + endpoint += "&source=user_upload" + } else { + endpoint += "&source=session_download" } - - // Default: list downloads for a session - if err := RequireSessionID(); err != nil { + req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint, nil) + if err != nil { return err } - - ctx, cancel := GetContextWithTimeout(cmd.Context()) - defer cancel() - - params := &api.FileListDownloadsParams{} - resp, err := client.Client().FileListDownloadsWithResponse(ctx, sessionID, params) + resp, err := client.HTTPClient().Do(req) if err != nil { return fmt.Errorf("API request failed: %w", err) } - - if err := HandleAPIResponse(resp.HTTPResponse, resp.Body); err != nil { + defer func() { _ = resp.Body.Close() }() + body, err := io.ReadAll(resp.Body) + if err != nil { return err } - - var fileNames []string - if resp.JSON200 != nil { - for _, f := range resp.JSON200.Files { - fileNames = append(fileNames, f.Name) - } + if err := HandleAPIResponse(resp, body); err != nil { + return err + } + var page sessionFilesPage + if err := json.Unmarshal(body, &page); err != nil { + return fmt.Errorf("failed to parse files response: %w", err) } - if printed, err := PrintListOrEmpty(fileNames, fmt.Sprintf("No downloaded files in session %s.", sessionID)); err != nil { + if printed, err := PrintListOrEmpty(page.Files, fmt.Sprintf("No files in session %s.", sessionID)); err != nil { return err } else if printed { return nil } - - if !IsJSONOutput() { - fmt.Printf("Downloaded files in session %s:\n", sessionID) - fmt.Println("Fetch locally with: notte files download ") - fmt.Println() - } - return formatter.Print(fileNames) + return GetFormatter().Print(page.Files) } func runFilesUpload(cmd *cobra.Command, args []string) error { @@ -293,6 +282,9 @@ func runFilesUpload(cmd *cobra.Command, args []string) error { if fileInfo.IsDir() { return fmt.Errorf("path is a directory, not a file: %s", filePath) } + if err := RequireSessionID(); err != nil { + return err + } client, err := GetClient() if err != nil { @@ -321,56 +313,41 @@ func runFilesUpload(cmd *cobra.Command, args []string) error { _ = writer.Close() - // Get the filename to use in the API call filename := filepath.Base(filePath) - ctx, cancel := GetContextWithTimeout(cmd.Context()) defer cancel() - - params := &api.FileUploadParams{} - resp, err := client.Client().FileUploadWithBodyWithResponse( - ctx, - filename, - params, - writer.FormDataContentType(), - &buf, - ) + req, err := http.NewRequestWithContext(ctx, http.MethodPost, sessionFilesURL(client.BaseURL(), ""), &buf) + if err != nil { + return err + } + req.Header.Set("Content-Type", writer.FormDataContentType()) + resp, err := client.HTTPClient().Do(req) if err != nil { return fmt.Errorf("API request failed: %w", err) } - - if err := HandleAPIResponse(resp.HTTPResponse, resp.Body); err != nil { + defer func() { _ = resp.Body.Close() }() + body, err := io.ReadAll(resp.Body) + if err != nil { return err } - - formatter := GetFormatter() - if resp.JSON200 != nil && resp.JSON200.Success { - if IsJSONOutput() { - return formatter.Print(resp.JSON200) - } - return PrintResult(fmt.Sprintf("File uploaded successfully: %s", filename), map[string]any{ - "filename": filename, - "success": true, - }) + if err := HandleAPIResponse(resp, body); err != nil { + return err } - - return formatter.Print(resp.JSON200) + var uploaded sessionFile + if err := json.Unmarshal(body, &uploaded); err != nil { + return fmt.Errorf("failed to parse upload response: %w", err) + } + return PrintResult(fmt.Sprintf("File uploaded successfully: %s", filename), map[string]any{ + "file": uploaded, + }) } func runFilesDownload(cmd *cobra.Command, args []string) error { - filename := args[0] - - source, err := resolveFilesSource(filesDownloadFrom, false, false) - if err != nil { + fileID := args[0] + if err := RequireSessionID(); err != nil { return err } - if source == filesSourceSession { - if err := RequireSessionID(); err != nil { - return err - } - } - client, err := GetClient() if err != nil { return err @@ -379,57 +356,56 @@ func runFilesDownload(cmd *cobra.Command, args []string) error { ctx, cancel := GetContextWithTimeout(cmd.Context()) defer cancel() - var httpResponse *http.Response - var responseBody []byte - if source == filesSourceUploads { - httpResponse, responseBody, err = client.DownloadUploadedFile(ctx, filename) - if err != nil { - return fmt.Errorf("API request failed: %w", err) + req, err := http.NewRequestWithContext( + ctx, http.MethodGet, sessionFilesURL(client.BaseURL(), "/"+url.PathEscape(fileID)), nil, + ) + if err != nil { + return err + } + resp, err := client.HTTPClient().Do(req) + if err != nil { + return fmt.Errorf("API request failed: %w", err) + } + defer func() { _ = resp.Body.Close() }() + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + body, readErr := io.ReadAll(resp.Body) + if readErr != nil { + return readErr } - } else { - params := &api.FileDownloadParams{} - resp, err := client.Client().FileDownloadWithResponse( - ctx, - sessionID, - filename, - params, - ) - if err != nil { - return fmt.Errorf("API request failed: %w", err) + return HandleAPIResponse(resp, body) + } + outputPath := filesDownloadOutput + if outputPath == "" { + outputPath = fileID + if _, params, parseErr := mime.ParseMediaType(resp.Header.Get("Content-Disposition")); parseErr == nil { + if filename := filepath.Base(params["filename"]); filename != "." && filename != "" { + outputPath = filename + } } - httpResponse = resp.HTTPResponse - responseBody = resp.Body } - - if err := HandleAPIResponse(httpResponse, responseBody); err != nil { + destinationPath, err := resolveDownloadOutputPath(outputPath) + if err != nil { return err } - - // Parse the JSON response to get the presigned URL - var downloadResp struct { - URL string `json:"url"` - } - if err := json.Unmarshal(responseBody, &downloadResp); err != nil { - return fmt.Errorf("failed to parse download response: %w", err) + temporary, err := os.CreateTemp(filepath.Dir(destinationPath), ".notte-download-*") + if err != nil { + return err } - - if downloadResp.URL == "" { - return fmt.Errorf("no download URL in response") + temporaryPath := temporary.Name() + defer func() { _ = os.Remove(temporaryPath) }() + if _, err := io.Copy(temporary, resp.Body); err != nil { + _ = temporary.Close() + return err } - - // Determine output path - outputPath := filesDownloadOutput - if outputPath == "" { - outputPath = filename + if err := temporary.Close(); err != nil { + return err } - - if err := downloadFileWithContext(ctx, downloadResp.URL, outputPath); err != nil { - return fmt.Errorf("failed to download file: %w", err) + if err := os.Rename(temporaryPath, destinationPath); err != nil { + return err } - return PrintResult(fmt.Sprintf("File downloaded successfully: %s", outputPath), map[string]any{ - "filename": filename, - "path": outputPath, - "success": true, + "id": fileID, + "path": outputPath, + "success": true, }) } diff --git a/internal/cmd/files_test.go b/internal/cmd/files_test.go index 6291fc6..fb12205 100644 --- a/internal/cmd/files_test.go +++ b/internal/cmd/files_test.go @@ -137,7 +137,7 @@ func TestRunFilesListUploads(t *testing.T) { defer server.Close() env.SetEnv("NOTTE_API_URL", server.URL()) - server.AddResponse("/storage/uploads", 200, `{"files":[{"name":"a.txt","file_ext":".txt","size":100}]}`) + server.AddResponse("/sessions/sess_123/files", 200, `{"files":[{"id":"f1","session_id":"sess_123","filename":"a.txt","mime_type":"text/plain","size":100,"checksum":"abc","created_at":"2026-08-21T00:00:00Z","expires_at":"2026-08-22T00:00:00Z","source":"user_upload"}],"total":1,"limit":1000,"offset":0}`) origUploadsFlag := filesListUploadsFlag origFrom := filesListFrom @@ -149,7 +149,7 @@ func TestRunFilesListUploads(t *testing.T) { }) filesListUploadsFlag = false filesListFrom = filesSourceUploads - sessionID = "" + sessionID = "sess_123" origFormat := outputFormat outputFormat = "json" @@ -178,7 +178,7 @@ func TestRunFilesListUploadsEmpty(t *testing.T) { defer server.Close() env.SetEnv("NOTTE_API_URL", server.URL()) - server.AddResponse("/storage/uploads", 200, `{"files":[]}`) + server.AddResponse("/sessions/sess_123/files", 200, `{"files":[],"total":0,"limit":1000,"offset":0}`) origUploadsFlag := filesListUploadsFlag origFrom := filesListFrom @@ -190,7 +190,7 @@ func TestRunFilesListUploadsEmpty(t *testing.T) { }) filesListUploadsFlag = true filesListFrom = "" - sessionID = "" + sessionID = "sess_123" origFormat := outputFormat outputFormat = "text" @@ -206,7 +206,7 @@ func TestRunFilesListUploadsEmpty(t *testing.T) { } }) - if !strings.Contains(stdout, "No uploaded files.") { + if !strings.Contains(stdout, "No files in session") { t.Fatalf("expected empty message, got %q", stdout) } } @@ -219,7 +219,7 @@ func TestRunFilesListDownloads(t *testing.T) { defer server.Close() env.SetEnv("NOTTE_API_URL", server.URL()) - server.AddResponse("/storage/sess_123/downloads", 200, `{"files":[{"name":"b.txt","file_ext":".txt","size":200}]}`) + server.AddResponse("/sessions/sess_123/files", 200, `{"files":[{"id":"f2","session_id":"sess_123","filename":"b.txt","mime_type":"text/plain","size":200,"checksum":"abc","created_at":"2026-08-21T00:00:00Z","expires_at":"2026-08-22T00:00:00Z","source":"session_download"}],"total":1,"limit":1000,"offset":0}`) origDownloadsFlag := filesListDownloadsFlag origFrom := filesListFrom @@ -306,7 +306,10 @@ func TestRunFilesUpload(t *testing.T) { } t.Cleanup(func() { _ = os.Remove(tmpFile.Name()) }) - server.AddResponse("/storage/uploads/"+filepath.Base(tmpFile.Name()), 200, `{"success":true}`) + server.AddResponse("/sessions/sess_123/files", 201, `{"id":"f1","session_id":"sess_123","filename":"`+filepath.Base(tmpFile.Name())+`","mime_type":"text/plain","size":5,"checksum":"abc","created_at":"2026-08-21T00:00:00Z","expires_at":"2026-08-22T00:00:00Z","source":"user_upload"}`) + origSession := sessionID + sessionID = "sess_123" + t.Cleanup(func() { sessionID = origSession }) origFormat := outputFormat outputFormat = "text" @@ -345,35 +348,23 @@ func TestRunFilesDownload(t *testing.T) { env := testutil.SetupTestEnv(t) env.SetEnv("NOTTE_API_KEY", "test-key") - // Create a server for the actual file content (simulating S3) - fileServer := testutil.NewMockServer() - defer fileServer.Close() - fileServer.AddResponseWithHeaders("/file.txt", 200, "filedata", map[string]string{ - "Content-Type": "application/octet-stream", - }) - - // Create the API server that returns the presigned URL server := testutil.NewMockServer() defer server.Close() env.SetEnv("NOTTE_API_URL", server.URL()) origSession := sessionID - origFrom := filesDownloadFrom origOutput := filesDownloadOutput t.Cleanup(func() { sessionID = origSession - filesDownloadFrom = origFrom filesDownloadOutput = origOutput }) sessionID = "sess_123" - filesDownloadFrom = "" outDir := t.TempDir() outputPath := filepath.Join(outDir, "download.txt") filesDownloadOutput = outputPath - // API returns JSON with the presigned URL pointing to our file server - server.AddResponse("/storage/sess_123/downloads/file.txt", 200, `{"url":"`+fileServer.URL()+`/file.txt"}`) + server.AddResponse("/sessions/sess_123/files/file-id", 200, "filedata") origFormat := outputFormat outputFormat = "text" @@ -383,7 +374,7 @@ func TestRunFilesDownload(t *testing.T) { cmd.SetContext(context.Background()) stdout, _ := testutil.CaptureOutput(func() { - err := runFilesDownload(cmd, []string{"file.txt"}) + err := runFilesDownload(cmd, []string{"file-id"}) if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -406,33 +397,24 @@ func TestRunFilesDownloadFromUploads(t *testing.T) { env.SetEnv("NOTTE_API_KEY", "test-key") env.SetEnv("NOTTE_SESSION_ID", "") - fileServer := testutil.NewMockServer() - defer fileServer.Close() - fileServer.AddResponseWithHeaders("/input.txt", 200, "uploaded-file-data", map[string]string{ - "Content-Type": "application/octet-stream", - }) - server := testutil.NewMockServer() defer server.Close() env.SetEnv("NOTTE_API_URL", server.URL()) - server.AddResponse("/storage/uploads/input.txt", 200, `{"url":"`+fileServer.URL()+`/input.txt"}`) + server.AddResponse("/sessions/sess_123/files/upload-id", 200, "uploaded-file-data") origSession := sessionID - origFrom := filesDownloadFrom origOutput := filesDownloadOutput t.Cleanup(func() { sessionID = origSession - filesDownloadFrom = origFrom filesDownloadOutput = origOutput }) - sessionID = "" - filesDownloadFrom = filesSourceUploads + sessionID = "sess_123" filesDownloadOutput = filepath.Join(t.TempDir(), "input.txt") cmd := &cobra.Command{} cmd.SetContext(context.Background()) - if err := runFilesDownload(cmd, []string{"input.txt"}); err != nil { + if err := runFilesDownload(cmd, []string{"upload-id"}); err != nil { t.Fatalf("unexpected error: %v", err) } @@ -455,11 +437,8 @@ func TestRunFilesDownloadMissingSession(t *testing.T) { t.Cleanup(func() { config.SetTestConfigDir("") }) origSession := sessionID - origFrom := filesDownloadFrom t.Cleanup(func() { sessionID = origSession }) - t.Cleanup(func() { filesDownloadFrom = origFrom }) sessionID = "" - filesDownloadFrom = "" cmd := &cobra.Command{} cmd.SetContext(context.Background()) @@ -482,7 +461,7 @@ func TestResolveFilesSource(t *testing.T) { want string wantErr bool }{ - {name: "defaults to session", want: filesSourceSession}, + {name: "defaults to all"}, {name: "from uploads", from: filesSourceUploads, want: filesSourceUploads}, {name: "from session", from: filesSourceSession, want: filesSourceSession}, {name: "legacy uploads", uploads: true, want: filesSourceUploads}, diff --git a/internal/cmd/sessions_test.go b/internal/cmd/sessions_test.go index 6d49b94..ae0c7fe 100644 --- a/internal/cmd/sessions_test.go +++ b/internal/cmd/sessions_test.go @@ -115,7 +115,6 @@ func TestRunSessionsStart(t *testing.T) { origVH := SessionStartViewportHeight origUA := SessionStartUserAgent origCDP := SessionStartCdpUrl - origFileStorage := SessionStartUseFileStorage t.Cleanup(func() { SessionStartHeadless = origHeadless SessionStartBrowserType = origBrowser @@ -126,7 +125,6 @@ func TestRunSessionsStart(t *testing.T) { SessionStartViewportHeight = origVH SessionStartUserAgent = origUA SessionStartCdpUrl = origCDP - SessionStartUseFileStorage = origFileStorage }) SessionStartHeadless = false @@ -138,7 +136,6 @@ func TestRunSessionsStart(t *testing.T) { SessionStartViewportHeight = 720 SessionStartUserAgent = "test-agent" SessionStartCdpUrl = "ws://cdp" - SessionStartUseFileStorage = true origFormat := outputFormat outputFormat = "json" @@ -148,11 +145,9 @@ func TestRunSessionsStart(t *testing.T) { cmd.Flags().BoolVar(&SessionStartHeadless, "headless", true, "") cmd.Flags().BoolVar(&sessionsStartProxy, "proxy", false, "") cmd.Flags().BoolVar(&SessionStartSolveCaptchas, "solve-captchas", false, "") - cmd.Flags().BoolVar(&SessionStartUseFileStorage, "file-storage", false, "") _ = cmd.Flags().Set("headless", "false") _ = cmd.Flags().Set("proxy", "true") _ = cmd.Flags().Set("solve-captchas", "true") - _ = cmd.Flags().Set("file-storage", "true") cmd.SetContext(context.Background()) stdout, _ := testutil.CaptureOutput(func() { diff --git a/internal/cmd/sessionstart_flags.gen.go b/internal/cmd/sessionstart_flags.gen.go index 3ceddbc..51e53a6 100644 --- a/internal/cmd/sessionstart_flags.gen.go +++ b/internal/cmd/sessionstart_flags.gen.go @@ -45,9 +45,6 @@ var ( // Whether to try to automatically solve captchas SessionStartSolveCaptchas bool - // Whether FileStorage should be attached to the session. - SessionStartUseFileStorage bool - // The user agent to use for the session SessionStartUserAgent string @@ -82,7 +79,6 @@ func RegisterSessionStartFlags(cmd *cobra.Command) { cmd.Flags().BoolVar(&SessionStartProfilePersist, "profile-persist", false, "Whether to save browser state to profile on session close (API default: false)") cmd.Flags().StringVar(&SessionStartScreenshotType, "screenshot-type", "", "The type of screenshot to use for the session. (API default: last_action) (raw, full, last_action)") cmd.Flags().BoolVar(&SessionStartSolveCaptchas, "solve-captchas", false, "Whether to try to automatically solve captchas (API default: true)") - cmd.Flags().BoolVar(&SessionStartUseFileStorage, "use-file-storage", false, "Whether FileStorage should be attached to the session. (API default: true)") cmd.Flags().StringVar(&SessionStartUserAgent, "user-agent", "", "The user agent to use for the session") cmd.Flags().StringVar(&SessionStartVaultId, "vault-id", "", "The vault to use for the session") cmd.Flags().IntVar(&SessionStartViewportHeight, "viewport-height", 0, "The height of the viewport") @@ -153,10 +149,6 @@ func BuildSessionStartRequest(cmd *cobra.Command) (*api.ApiSessionStartRequest, body.SolveCaptchas = &SessionStartSolveCaptchas } - if cmd.Flags().Changed("use-file-storage") { - body.UseFileStorage = &SessionStartUseFileStorage - } - if SessionStartUserAgent != "" { body.UserAgent = &SessionStartUserAgent } diff --git a/internal/cmd/sessionstart_optout.go b/internal/cmd/sessionstart_optout.go index ca6ac6d..a18716d 100644 --- a/internal/cmd/sessionstart_optout.go +++ b/internal/cmd/sessionstart_optout.go @@ -22,13 +22,10 @@ import ( // // --no- rather than --disable- specifically because Chromium's own flags are // --disable-* (--disable-gpu, --disable-extensions) and this command forwards -// them verbatim through --chrome-args. Keeping the prefixes distinct means -// `--no-file-storage --chrome-args="--disable-gpu"` reads unambiguously as one -// Notte flag and one browser flag. +// them verbatim through --chrome-args. var ( sessionsStartHeaded bool sessionsStartNoSolveCaptchas bool - sessionsStartNoFileStorage bool ) // sessionStartOptOut pairs a new negative flag with the generated flag it @@ -57,12 +54,6 @@ func sessionStartOptOuts() []sessionStartOptOut { set: &sessionsStartNoSolveCaptchas, apply: func(b *api.ApiSessionStartRequest, enabled bool) { b.SolveCaptchas = &enabled }, }, - { - negative: "no-file-storage", - original: "use-file-storage", - set: &sessionsStartNoFileStorage, - apply: func(b *api.ApiSessionStartRequest, enabled bool) { b.UseFileStorage = &enabled }, - }, } } @@ -73,11 +64,6 @@ func registerSessionStartOptOutFlags(cmd *cobra.Command) { "Run with a visible browser window instead of headless") cmd.Flags().BoolVar(&sessionsStartNoSolveCaptchas, "no-solve-captchas", false, "Do not attempt to solve captchas automatically") - // No backticks in usage strings: cobra's UnquoteUsage treats the first - // backquoted span as the flag's value placeholder, so this rendered as - // "--no-file-storage notte page download" in --help. - cmd.Flags().BoolVar(&sessionsStartNoFileStorage, "no-file-storage", false, - "Do not attach FileStorage. Disables 'notte page download' and 'notte files --from session'") } // validateSessionStartOptOuts rejects a pair whose two spellings were both diff --git a/internal/cmd/sessionstart_optout_test.go b/internal/cmd/sessionstart_optout_test.go index efefcbc..b203c77 100644 --- a/internal/cmd/sessionstart_optout_test.go +++ b/internal/cmd/sessionstart_optout_test.go @@ -14,7 +14,6 @@ func newOptOutCmd() *cobra.Command { cmd := &cobra.Command{Use: "start", RunE: func(*cobra.Command, []string) error { return nil }} cmd.Flags().BoolVar(&SessionStartHeadless, "headless", false, "headless") cmd.Flags().BoolVar(&SessionStartSolveCaptchas, "solve-captchas", false, "solve captchas") - cmd.Flags().BoolVar(&SessionStartUseFileStorage, "use-file-storage", false, "file storage") registerSessionStartOptOutFlags(cmd) return cmd } @@ -24,7 +23,6 @@ func runOptOut(t *testing.T, args ...string) (*api.ApiSessionStartRequest, error // Package-level flag vars are shared; reset before each case. sessionsStartHeaded = false sessionsStartNoSolveCaptchas = false - sessionsStartNoFileStorage = false cmd := newOptOutCmd() cmd.SetArgs(args) @@ -49,9 +47,6 @@ func TestOptOutsLeaveBodyUntouchedWhenAbsent(t *testing.T) { if body.SolveCaptchas != nil { t.Errorf("SolveCaptchas = %v, want nil when --no-solve-captchas is omitted", *body.SolveCaptchas) } - if body.UseFileStorage != nil { - t.Errorf("UseFileStorage = %v, want nil when --no-file-storage is omitted", *body.UseFileStorage) - } } func TestOptOutsInvertTheirCounterpart(t *testing.T) { @@ -83,13 +78,6 @@ func TestOptOutsInvertTheirCounterpart(t *testing.T) { get: func(b *api.ApiSessionStartRequest) *bool { return b.SolveCaptchas }, want: false, }, - { - name: "--no-file-storage sends use_file_storage=false", - args: []string{"--no-file-storage"}, - field: "UseFileStorage", - get: func(b *api.ApiSessionStartRequest) *bool { return b.UseFileStorage }, - want: false, - }, } for _, tc := range tests { @@ -117,7 +105,6 @@ func TestConflictingPairIsRejected(t *testing.T) { {"--headed", "--headless"}, {"--headed", "--headless=false"}, {"--no-solve-captchas", "--solve-captchas"}, - {"--no-file-storage", "--use-file-storage"}, } { _, err := runOptOut(t, args...) if err == nil { @@ -131,7 +118,7 @@ func TestConflictingPairIsRejected(t *testing.T) { // when they cannot rely on the server default. func TestOriginalFlagsStillWorkAlone(t *testing.T) { cmd := newOptOutCmd() - for _, name := range []string{"headless", "solve-captchas", "use-file-storage"} { + for _, name := range []string{"headless", "solve-captchas"} { f := cmd.Flags().Lookup(name) if f == nil { t.Errorf("--%s should still be registered", name)