@@ -704,3 +704,139 @@ func (c *Client) FetchAvailableModels(ctx context.Context, accessToken, projectI
704704
705705 return nil , nil , lastErr
706706}
707+
708+ // ── Privacy API ──────────────────────────────────────────────────────
709+
710+ // privacyBaseURL 隐私设置 API 仅使用 daily 端点(与 Antigravity 客户端行为一致)
711+ const privacyBaseURL = antigravityDailyBaseURL
712+
713+ // SetUserSettingsRequest setUserSettings 请求体
714+ type SetUserSettingsRequest struct {
715+ UserSettings map [string ]any `json:"user_settings"`
716+ }
717+
718+ // FetchUserInfoRequest fetchUserInfo 请求体
719+ type FetchUserInfoRequest struct {
720+ Project string `json:"project"`
721+ }
722+
723+ // FetchUserInfoResponse fetchUserInfo 响应体
724+ type FetchUserInfoResponse struct {
725+ UserSettings map [string ]any `json:"userSettings,omitempty"`
726+ RegionCode string `json:"regionCode,omitempty"`
727+ }
728+
729+ // IsPrivate 判断隐私是否已设置:userSettings 为空或不含 telemetryEnabled 表示已设置
730+ func (r * FetchUserInfoResponse ) IsPrivate () bool {
731+ if r == nil || r .UserSettings == nil {
732+ return true
733+ }
734+ _ , hasTelemetry := r .UserSettings ["telemetryEnabled" ]
735+ return ! hasTelemetry
736+ }
737+
738+ // SetUserSettingsResponse setUserSettings 响应体
739+ type SetUserSettingsResponse struct {
740+ UserSettings map [string ]any `json:"userSettings,omitempty"`
741+ }
742+
743+ // IsSuccess 判断 setUserSettings 是否成功:返回 {"userSettings":{}} 且无 telemetryEnabled
744+ func (r * SetUserSettingsResponse ) IsSuccess () bool {
745+ if r == nil {
746+ return false
747+ }
748+ // userSettings 为 nil 或空 map 均视为成功
749+ if r .UserSettings == nil || len (r .UserSettings ) == 0 {
750+ return true
751+ }
752+ // 如果包含 telemetryEnabled 字段,说明未成功清除
753+ _ , hasTelemetry := r .UserSettings ["telemetryEnabled" ]
754+ return ! hasTelemetry
755+ }
756+
757+ // SetUserSettings 调用 setUserSettings API 设置用户隐私,返回解析后的响应
758+ func (c * Client ) SetUserSettings (ctx context.Context , accessToken string ) (* SetUserSettingsResponse , error ) {
759+ // 发送空 user_settings 以清除隐私设置
760+ payload := SetUserSettingsRequest {UserSettings : map [string ]any {}}
761+ bodyBytes , err := json .Marshal (payload )
762+ if err != nil {
763+ return nil , fmt .Errorf ("序列化请求失败: %w" , err )
764+ }
765+
766+ apiURL := privacyBaseURL + "/v1internal:setUserSettings"
767+ req , err := http .NewRequestWithContext (ctx , http .MethodPost , apiURL , bytes .NewReader (bodyBytes ))
768+ if err != nil {
769+ return nil , fmt .Errorf ("创建请求失败: %w" , err )
770+ }
771+ req .Header .Set ("Authorization" , "Bearer " + accessToken )
772+ req .Header .Set ("Content-Type" , "application/json" )
773+ req .Header .Set ("Accept" , "*/*" )
774+ req .Header .Set ("User-Agent" , GetUserAgent ())
775+ req .Header .Set ("X-Goog-Api-Client" , "gl-node/22.21.1" )
776+ req .Host = "daily-cloudcode-pa.googleapis.com"
777+
778+ resp , err := c .httpClient .Do (req )
779+ if err != nil {
780+ return nil , fmt .Errorf ("setUserSettings 请求失败: %w" , err )
781+ }
782+ defer func () { _ = resp .Body .Close () }()
783+
784+ respBody , err := io .ReadAll (resp .Body )
785+ if err != nil {
786+ return nil , fmt .Errorf ("读取响应失败: %w" , err )
787+ }
788+
789+ if resp .StatusCode != http .StatusOK {
790+ return nil , fmt .Errorf ("setUserSettings 失败 (HTTP %d): %s" , resp .StatusCode , string (respBody ))
791+ }
792+
793+ var result SetUserSettingsResponse
794+ if err := json .Unmarshal (respBody , & result ); err != nil {
795+ return nil , fmt .Errorf ("响应解析失败: %w" , err )
796+ }
797+
798+ return & result , nil
799+ }
800+
801+ // FetchUserInfo 调用 fetchUserInfo API 获取用户隐私设置状态
802+ func (c * Client ) FetchUserInfo (ctx context.Context , accessToken , projectID string ) (* FetchUserInfoResponse , error ) {
803+ reqBody := FetchUserInfoRequest {Project : projectID }
804+ bodyBytes , err := json .Marshal (reqBody )
805+ if err != nil {
806+ return nil , fmt .Errorf ("序列化请求失败: %w" , err )
807+ }
808+
809+ apiURL := privacyBaseURL + "/v1internal:fetchUserInfo"
810+ req , err := http .NewRequestWithContext (ctx , http .MethodPost , apiURL , bytes .NewReader (bodyBytes ))
811+ if err != nil {
812+ return nil , fmt .Errorf ("创建请求失败: %w" , err )
813+ }
814+ req .Header .Set ("Authorization" , "Bearer " + accessToken )
815+ req .Header .Set ("Content-Type" , "application/json" )
816+ req .Header .Set ("Accept" , "*/*" )
817+ req .Header .Set ("User-Agent" , GetUserAgent ())
818+ req .Header .Set ("X-Goog-Api-Client" , "gl-node/22.21.1" )
819+ req .Host = "daily-cloudcode-pa.googleapis.com"
820+
821+ resp , err := c .httpClient .Do (req )
822+ if err != nil {
823+ return nil , fmt .Errorf ("fetchUserInfo 请求失败: %w" , err )
824+ }
825+ defer func () { _ = resp .Body .Close () }()
826+
827+ respBody , err := io .ReadAll (resp .Body )
828+ if err != nil {
829+ return nil , fmt .Errorf ("读取响应失败: %w" , err )
830+ }
831+
832+ if resp .StatusCode != http .StatusOK {
833+ return nil , fmt .Errorf ("fetchUserInfo 失败 (HTTP %d): %s" , resp .StatusCode , string (respBody ))
834+ }
835+
836+ var result FetchUserInfoResponse
837+ if err := json .Unmarshal (respBody , & result ); err != nil {
838+ return nil , fmt .Errorf ("响应解析失败: %w" , err )
839+ }
840+
841+ return & result , nil
842+ }
0 commit comments