@whop/cli 0.8.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -6316,7 +6316,7 @@ var native_spec_default = {
6316
6316
  "x-whop-summary": "Turn a plan into a shareable, prefilled checkout link."
6317
6317
  },
6318
6318
  {
6319
- description: "The Referrals API covers your Whop partner activity: the users you referred onto Whop, the businesses you referred and the earnings generated from their processing volume, and the partner leaderboard.\n\nUse it to enroll as a Whop partner, list the users you referred, list your referred businesses and review their earnings, and see the partner leaderboard.\n",
6319
+ description: "The Partners API covers your Whop partner activity: the users you referred onto Whop, the businesses you referred and the earnings generated from their processing volume, and the partner leaderboard.\n\nUse it to enroll as a Whop partner, list the users you referred, list your referred businesses and review their earnings, and see the partner leaderboard.\n",
6320
6320
  name: "Partners",
6321
6321
  "x-whop-summary": "The users and businesses you referred to Whop, and what you earn from them."
6322
6322
  },
@@ -6407,7 +6407,7 @@ var native_spec_default = {
6407
6407
  },
6408
6408
  {
6409
6409
  description: "Refer users and businesses to Whop and track what you earn.",
6410
- name: "Referrals",
6410
+ name: "Partners",
6411
6411
  tags: [
6412
6412
  "Partners"
6413
6413
  ]
@@ -8559,7 +8559,7 @@ var native_spec_default = {
8559
8559
  type: "string"
8560
8560
  },
8561
8561
  placements: {
8562
- description: "'automatic' (Advantage+) or a list of { platform, positions }."
8562
+ description: "'automatic' (Advantage+) or a list of { platform, positions }. Omit positions to target all of a platform's.\n\nValid positions per platform:\n\n- `facebook`: `feed`, `right_hand_column`, `marketplace`, `search`, `profile_feed`, `notification`, `story`, `instream_video`, `facebook_reels`, `facebook_reels_overlay`, `biz_disco_feed`\n- `instagram`: `stream`, `story`, `explore`, `explore_home`, `reels`, `profile_feed`, `profile_reels`, `ig_search`\n- `messenger`: `story`\n- `audience_network`: `classic`, `rewarded_video`\n- `threads`: `threads_stream`\n- `whatsapp`: `status`"
8563
8563
  },
8564
8564
  regions: {
8565
8565
  description: "Geo targeting: { include / exclude: { countries (ISO 3166-1), regions (states/provinces as ISO 3166-2, e.g. US-CA), cities (keyed), zips } }.",
@@ -8849,7 +8849,7 @@ var native_spec_default = {
8849
8849
  type: "string"
8850
8850
  },
8851
8851
  placements: {
8852
- description: "'automatic' (Advantage+) or a list of { platform, positions }."
8852
+ description: "'automatic' (Advantage+) or a list of { platform, positions }. Omit positions to target all of a platform's.\n\nValid positions per platform:\n\n- `facebook`: `feed`, `right_hand_column`, `marketplace`, `search`, `profile_feed`, `notification`, `story`, `instream_video`, `facebook_reels`, `facebook_reels_overlay`, `biz_disco_feed`\n- `instagram`: `stream`, `story`, `explore`, `explore_home`, `reels`, `profile_feed`, `profile_reels`, `ig_search`\n- `messenger`: `story`\n- `audience_network`: `classic`, `rewarded_video`\n- `threads`: `threads_stream`\n- `whatsapp`: `status`"
8853
8853
  },
8854
8854
  regions: {
8855
8855
  description: "Geo targeting: { include / exclude: { countries (ISO 3166-1), regions (states/provinces as ISO 3166-2, e.g. US-CA), cities (keyed), zips } }.",
@@ -15170,7 +15170,7 @@ var native_spec_default = {
15170
15170
  },
15171
15171
  "/partners": {
15172
15172
  post: {
15173
- description: "Enrolls the calling user in the Whop partner program, making their business referrals eligible for earnings. Idempotent \u2014 enrolling again keeps the original enrollment time.",
15173
+ description: "Enrolls the calling user in the Whop partner program, making their partner businesses eligible for earnings. Idempotent \u2014 enrolling again keeps the original enrollment time.",
15174
15174
  operationId: "create",
15175
15175
  responses: {
15176
15176
  "200": {
@@ -15257,7 +15257,7 @@ var native_spec_default = {
15257
15257
  }
15258
15258
  },
15259
15259
  {
15260
- description: "Number of business referrals to return from the start of the window.",
15260
+ description: "Number of partner businesses to return from the start of the window.",
15261
15261
  in: "query",
15262
15262
  name: "first",
15263
15263
  required: false,
@@ -15277,7 +15277,7 @@ var native_spec_default = {
15277
15277
  }
15278
15278
  },
15279
15279
  {
15280
- description: "Number of business referrals to return from the end of the window.",
15280
+ description: "Number of partner businesses to return from the end of the window.",
15281
15281
  in: "query",
15282
15282
  name: "last",
15283
15283
  required: false,
@@ -15296,7 +15296,7 @@ var native_spec_default = {
15296
15296
  }
15297
15297
  },
15298
15298
  {
15299
- description: "The field to sort business referrals by.",
15299
+ description: "The field to sort partner businesses by.",
15300
15300
  in: "query",
15301
15301
  name: "order",
15302
15302
  required: false,
@@ -15328,7 +15328,7 @@ var native_spec_default = {
15328
15328
  }
15329
15329
  },
15330
15330
  {
15331
- description: "Only return business referrals created before this timestamp.",
15331
+ description: "Only return partner businesses created before this timestamp.",
15332
15332
  in: "query",
15333
15333
  name: "created_before",
15334
15334
  required: false,
@@ -15337,7 +15337,7 @@ var native_spec_default = {
15337
15337
  }
15338
15338
  },
15339
15339
  {
15340
- description: "Only return business referrals created after this timestamp.",
15340
+ description: "Only return partner businesses created after this timestamp.",
15341
15341
  in: "query",
15342
15342
  name: "created_after",
15343
15343
  required: false,
@@ -15421,7 +15421,7 @@ var native_spec_default = {
15421
15421
  ]
15422
15422
  },
15423
15423
  created_at: {
15424
- description: "When the business referral was created.",
15424
+ description: "When the partner business was created.",
15425
15425
  format: "date-time",
15426
15426
  type: "string"
15427
15427
  },
@@ -15491,7 +15491,7 @@ var native_spec_default = {
15491
15491
  ]
15492
15492
  },
15493
15493
  id: {
15494
- description: "Business referral ID.",
15494
+ description: "Partner business ID.",
15495
15495
  type: "string"
15496
15496
  },
15497
15497
  my_partner_tier: {
@@ -15504,7 +15504,7 @@ var native_spec_default = {
15504
15504
  },
15505
15505
  object: {
15506
15506
  enum: [
15507
- "business_referral"
15507
+ "partner_business"
15508
15508
  ],
15509
15509
  type: "string"
15510
15510
  },
@@ -15661,7 +15661,7 @@ var native_spec_default = {
15661
15661
  }
15662
15662
  }
15663
15663
  },
15664
- description: "business referrals listed"
15664
+ description: "partner businesses listed"
15665
15665
  },
15666
15666
  "400": {
15667
15667
  $ref: "#/components/responses/InvalidParameters",
@@ -15683,7 +15683,7 @@ var native_spec_default = {
15683
15683
  ]
15684
15684
  }
15685
15685
  ],
15686
- summary: "List partner business referrals",
15686
+ summary: "List a partner's referred businesses",
15687
15687
  tags: [
15688
15688
  "Partners"
15689
15689
  ]
@@ -15761,7 +15761,7 @@ var native_spec_default = {
15761
15761
  ]
15762
15762
  },
15763
15763
  created_at: {
15764
- description: "When the business referral was created.",
15764
+ description: "When the partner business was created.",
15765
15765
  format: "date-time",
15766
15766
  type: "string"
15767
15767
  },
@@ -15831,7 +15831,7 @@ var native_spec_default = {
15831
15831
  ]
15832
15832
  },
15833
15833
  id: {
15834
- description: "Business referral ID.",
15834
+ description: "Partner business ID.",
15835
15835
  type: "string"
15836
15836
  },
15837
15837
  my_partner_tier: {
@@ -15844,7 +15844,7 @@ var native_spec_default = {
15844
15844
  },
15845
15845
  object: {
15846
15846
  enum: [
15847
- "business_referral"
15847
+ "partner_business"
15848
15848
  ],
15849
15849
  type: "string"
15850
15850
  },
@@ -15962,11 +15962,11 @@ var native_spec_default = {
15962
15962
  }
15963
15963
  }
15964
15964
  },
15965
- description: "business referral retrieved"
15965
+ description: "partner business retrieved"
15966
15966
  },
15967
15967
  "404": {
15968
15968
  $ref: "#/components/responses/NotFound",
15969
- description: "no such business referral is visible to the credential"
15969
+ description: "no such partner business is visible to the credential"
15970
15970
  }
15971
15971
  },
15972
15972
  security: [
@@ -15976,7 +15976,7 @@ var native_spec_default = {
15976
15976
  ]
15977
15977
  }
15978
15978
  ],
15979
- summary: "Retrieve a partner business referral",
15979
+ summary: "Retrieve a referred business",
15980
15980
  tags: [
15981
15981
  "Partners"
15982
15982
  ],
@@ -15985,7 +15985,7 @@ var native_spec_default = {
15985
15985
  $ref: "#/components/parameters/ApiVersionDate"
15986
15986
  },
15987
15987
  {
15988
- description: "The business referral ID (a coma_ identifier).",
15988
+ description: "The partner business ID (a coma_ identifier).",
15989
15989
  in: "path",
15990
15990
  name: "id",
15991
15991
  required: true,
@@ -16005,7 +16005,7 @@ var native_spec_default = {
16005
16005
  $ref: "#/components/parameters/ApiVersionDate"
16006
16006
  },
16007
16007
  {
16008
- description: "The business referral ID (a coma_ identifier).",
16008
+ description: "The partner business ID (a coma_ identifier).",
16009
16009
  in: "path",
16010
16010
  name: "id",
16011
16011
  required: true,
@@ -16237,7 +16237,7 @@ var native_spec_default = {
16237
16237
  },
16238
16238
  object: {
16239
16239
  enum: [
16240
- "business_referral_earning"
16240
+ "partner_business_earning"
16241
16241
  ],
16242
16242
  type: "string"
16243
16243
  },
@@ -16459,7 +16459,7 @@ var native_spec_default = {
16459
16459
  ]
16460
16460
  }
16461
16461
  ],
16462
- summary: "List a partner business referral's earnings",
16462
+ summary: "List a partner's referred business earnings",
16463
16463
  tags: [
16464
16464
  "Partners"
16465
16465
  ]
@@ -16467,7 +16467,7 @@ var native_spec_default = {
16467
16467
  },
16468
16468
  "/partners/leaderboard": {
16469
16469
  get: {
16470
- description: "Ranks referrers by business referral earnings \u2014 all-time by default, or over the current day, month, year, or trailing 30 days \u2014 and includes the caller's own standing.",
16470
+ description: "Ranks referrers by partner business earnings \u2014 all-time by default, or over the current day, month, year, or trailing 30 days \u2014 and includes the caller's own standing.",
16471
16471
  operationId: "leaderboard",
16472
16472
  parameters: [
16473
16473
  {
@@ -16502,7 +16502,7 @@ var native_spec_default = {
16502
16502
  items: {
16503
16503
  properties: {
16504
16504
  first_referral_started_at: {
16505
- description: "When the referrer's earliest business referral became active.",
16505
+ description: "When the referrer's earliest partner business became active.",
16506
16506
  format: "date-time",
16507
16507
  type: "string"
16508
16508
  },
@@ -16590,7 +16590,7 @@ var native_spec_default = {
16590
16590
  description: "The caller's own standing; null when the caller has no referral earnings.",
16591
16591
  properties: {
16592
16592
  first_referral_started_at: {
16593
- description: "When the referrer's earliest business referral became active.",
16593
+ description: "When the referrer's earliest partner business became active.",
16594
16594
  format: "date-time",
16595
16595
  type: "string"
16596
16596
  },
@@ -23142,6 +23142,66 @@ var native_spec_default = {
23142
23142
  ]
23143
23143
  }
23144
23144
  },
23145
+ "/users/{id}/recommend_actions": {
23146
+ get: {
23147
+ description: "Lists the recommended actions computed for the user: personal suggestions (e.g. start a business or become an affiliate) pooled with the highest-impact actions across the accounts the user owns. Business actions are tagged with their `account_id`/`account_name`; personal actions leave those `null`. Self-only: `id` must be `me` or the authenticated user's own tag/username.",
23148
+ operationId: "recommend_actions",
23149
+ responses: {
23150
+ "200": {
23151
+ content: {
23152
+ "application/json": {
23153
+ schema: {
23154
+ properties: {
23155
+ data: {
23156
+ items: {
23157
+ $ref: "#/components/schemas/UserRecommendedAction"
23158
+ },
23159
+ type: "array"
23160
+ }
23161
+ },
23162
+ required: [
23163
+ "data"
23164
+ ],
23165
+ type: "object"
23166
+ }
23167
+ }
23168
+ },
23169
+ description: "recommended actions listed"
23170
+ },
23171
+ "401": {
23172
+ $ref: "#/components/responses/Unauthorized",
23173
+ description: "missing or invalid authentication"
23174
+ },
23175
+ "403": {
23176
+ $ref: "#/components/responses/Forbidden",
23177
+ description: "reading another user's recommended actions"
23178
+ }
23179
+ },
23180
+ security: [
23181
+ {
23182
+ bearerAuth: []
23183
+ }
23184
+ ],
23185
+ summary: "List Recommended Actions",
23186
+ tags: [
23187
+ "Users"
23188
+ ],
23189
+ parameters: [
23190
+ {
23191
+ $ref: "#/components/parameters/ApiVersionDate"
23192
+ },
23193
+ {
23194
+ description: "`me`, or the authenticated user's own `user_` tag or username.",
23195
+ in: "path",
23196
+ name: "id",
23197
+ required: true,
23198
+ schema: {
23199
+ type: "string"
23200
+ }
23201
+ }
23202
+ ]
23203
+ }
23204
+ },
23145
23205
  "/verifications": {
23146
23206
  get: {
23147
23207
  description: "Returns verifications for an account, including their status and any required actions.",
@@ -23419,10 +23479,11 @@ var native_spec_default = {
23419
23479
  ]
23420
23480
  },
23421
23481
  status: {
23422
- description: "Current verification state. `not_started` before any session has been created; `pending` while a session is in progress; `action_required` when items in `requested_information` need answers before review can continue; `approved` once verification succeeds; `rejected` if it fails. Call the Create Verification endpoint again to start a new session.",
23482
+ description: "Current verification state. `not_started` before any session has been created; `pending` while a session is in progress and needs the user's input; `processing` while the provider reviews submitted documents \u2014 nothing to do but wait; `action_required` when items in `requested_information` need answers before review can continue; `approved` once verification succeeds; `rejected` if it fails. Call the Create Verification endpoint again to start a new session.",
23423
23483
  enum: [
23424
23484
  "not_started",
23425
23485
  "pending",
23486
+ "processing",
23426
23487
  "approved",
23427
23488
  "rejected",
23428
23489
  "action_required"
@@ -23534,6 +23595,10 @@ var native_spec_default = {
23534
23595
  description: "Entity type for sole proprietors, such as `single_member_llc`. Supported values vary by country of incorporation \u2014 see [Business structures](/developer/verification/business-structures).",
23535
23596
  type: "string"
23536
23597
  },
23598
+ business_tax_identification_number: {
23599
+ description: "The business ID number of the company, as appropriate for the company's country. Examples are an Employer Identification Number (EIN) in the US, a Business Number in Canada, or a Company Number in the UK.",
23600
+ type: "string"
23601
+ },
23537
23602
  business_website: {
23538
23603
  description: "Business website URL. Whop store pages are not accepted.",
23539
23604
  type: "string"
@@ -23580,7 +23645,7 @@ var native_spec_default = {
23580
23645
  type: "string"
23581
23646
  },
23582
23647
  tax_identification_number: {
23583
- description: "SSN or ITIN. Tokenized in transit and never stored raw.",
23648
+ description: "The government-issued ID number of the person being verified \u2014 the individual for a KYC verification, or the business representative for a KYB verification \u2014 as appropriate for their country. Examples are a Social Security Number (SSN) in the US, or a Social Insurance Number in Canada.",
23584
23649
  type: "string"
23585
23650
  }
23586
23651
  },
@@ -23626,6 +23691,10 @@ var native_spec_default = {
23626
23691
  description: "Legal entity structure of the business, such as `private_corporation` or `sole_proprietorship`. Supported values vary by country of incorporation \u2014 see [Business structures](/developer/verification/business-structures).",
23627
23692
  type: "string"
23628
23693
  },
23694
+ business_tax_identification_number: {
23695
+ description: "The business ID number of the company, as appropriate for the company's country. Examples are an Employer Identification Number (EIN) in the US, a Business Number in Canada, or a Company Number in the UK.",
23696
+ type: "string"
23697
+ },
23629
23698
  business_website: {
23630
23699
  description: "Business website URL. Whop store pages are not accepted.",
23631
23700
  type: "string"
@@ -23646,7 +23715,7 @@ var native_spec_default = {
23646
23715
  type: "string"
23647
23716
  },
23648
23717
  tax_identification_number: {
23649
- description: "EIN. Tokenized in transit and never stored raw.",
23718
+ description: "The government-issued ID number of the person being verified \u2014 the individual for a KYC verification, or the business representative for a KYB verification \u2014 as appropriate for their country. Examples are a Social Security Number (SSN) in the US, or a Social Insurance Number in Canada.",
23650
23719
  type: "string"
23651
23720
  }
23652
23721
  },
@@ -23886,10 +23955,11 @@ var native_spec_default = {
23886
23955
  ]
23887
23956
  },
23888
23957
  status: {
23889
- description: "Current verification state. `not_started` before any session has been created; `pending` while a session is in progress; `action_required` when items in `requested_information` need answers before review can continue; `approved` once verification succeeds; `rejected` if it fails. Call the Create Verification endpoint again to start a new session.",
23958
+ description: "Current verification state. `not_started` before any session has been created; `pending` while a session is in progress and needs the user's input; `processing` while the provider reviews submitted documents \u2014 nothing to do but wait; `action_required` when items in `requested_information` need answers before review can continue; `approved` once verification succeeds; `rejected` if it fails. Call the Create Verification endpoint again to start a new session.",
23890
23959
  enum: [
23891
23960
  "not_started",
23892
23961
  "pending",
23962
+ "processing",
23893
23963
  "approved",
23894
23964
  "rejected",
23895
23965
  "action_required"
@@ -24134,10 +24204,11 @@ var native_spec_default = {
24134
24204
  ]
24135
24205
  },
24136
24206
  status: {
24137
- description: "Current verification state. `not_started` before any session has been created; `pending` while a session is in progress; `action_required` when items in `requested_information` need answers before review can continue; `approved` once verification succeeds; `rejected` if it fails. Call the Create Verification endpoint again to start a new session.",
24207
+ description: "Current verification state. `not_started` before any session has been created; `pending` while a session is in progress and needs the user's input; `processing` while the provider reviews submitted documents \u2014 nothing to do but wait; `action_required` when items in `requested_information` need answers before review can continue; `approved` once verification succeeds; `rejected` if it fails. Call the Create Verification endpoint again to start a new session.",
24138
24208
  enum: [
24139
24209
  "not_started",
24140
24210
  "pending",
24211
+ "processing",
24141
24212
  "approved",
24142
24213
  "rejected",
24143
24214
  "action_required"
@@ -24431,10 +24502,11 @@ var native_spec_default = {
24431
24502
  ]
24432
24503
  },
24433
24504
  status: {
24434
- description: "Current verification state. `not_started` before any session has been created; `pending` while a session is in progress; `action_required` when items in `requested_information` need answers before review can continue; `approved` once verification succeeds; `rejected` if it fails. Call the Create Verification endpoint again to start a new session.",
24505
+ description: "Current verification state. `not_started` before any session has been created; `pending` while a session is in progress and needs the user's input; `processing` while the provider reviews submitted documents \u2014 nothing to do but wait; `action_required` when items in `requested_information` need answers before review can continue; `approved` once verification succeeds; `rejected` if it fails. Call the Create Verification endpoint again to start a new session.",
24435
24506
  enum: [
24436
24507
  "not_started",
24437
24508
  "pending",
24509
+ "processing",
24438
24510
  "approved",
24439
24511
  "rejected",
24440
24512
  "action_required"
@@ -24527,6 +24599,10 @@ var native_spec_default = {
24527
24599
  {
24528
24600
  description: "Fields that can be updated on an individual (KYC) verification. At least one field is required.",
24529
24601
  properties: {
24602
+ business_tax_identification_number: {
24603
+ description: "The business ID number of the company, as appropriate for the company's country. Examples are an Employer Identification Number (EIN) in the US, a Business Number in Canada, or a Company Number in the UK.",
24604
+ type: "string"
24605
+ },
24530
24606
  country: {
24531
24607
  description: "Two-letter ISO 3166-1 country code, for example `US`, `DE`, or `GB`.",
24532
24608
  type: "string"
@@ -24651,6 +24727,10 @@ var native_spec_default = {
24651
24727
  type: "object"
24652
24728
  },
24653
24729
  type: "array"
24730
+ },
24731
+ tax_identification_number: {
24732
+ description: "The government-issued ID number of the person being verified \u2014 the individual for a KYC verification, or the business representative for a KYB verification \u2014 as appropriate for their country. Examples are a Social Security Number (SSN) in the US, or a Social Insurance Number in Canada.",
24733
+ type: "string"
24654
24734
  }
24655
24735
  },
24656
24736
  title: "UpdateIndividualVerification",
@@ -24696,6 +24776,10 @@ var native_spec_default = {
24696
24776
  description: "Legal entity structure of the business, such as `private_corporation` or `sole_proprietorship`. Supported values vary by country of incorporation \u2014 see [Business structures](/developer/verification/business-structures).",
24697
24777
  type: "string"
24698
24778
  },
24779
+ business_tax_identification_number: {
24780
+ description: "The business ID number of the company, as appropriate for the company's country. Examples are an Employer Identification Number (EIN) in the US, a Business Number in Canada, or a Company Number in the UK.",
24781
+ type: "string"
24782
+ },
24699
24783
  country: {
24700
24784
  description: "Two-letter ISO 3166-1 country code, for example `US`, `DE`, or `GB`.",
24701
24785
  type: "string"
@@ -24781,6 +24865,10 @@ var native_spec_default = {
24781
24865
  type: "object"
24782
24866
  },
24783
24867
  type: "array"
24868
+ },
24869
+ tax_identification_number: {
24870
+ description: "The government-issued ID number of the person being verified \u2014 the individual for a KYC verification, or the business representative for a KYB verification \u2014 as appropriate for their country. Examples are a Social Security Number (SSN) in the US, or a Social Insurance Number in Canada.",
24871
+ type: "string"
24784
24872
  }
24785
24873
  },
24786
24874
  title: "UpdateBusinessVerification",
@@ -25020,10 +25108,11 @@ var native_spec_default = {
25020
25108
  ]
25021
25109
  },
25022
25110
  status: {
25023
- description: "Current verification state. `not_started` before any session has been created; `pending` while a session is in progress; `action_required` when items in `requested_information` need answers before review can continue; `approved` once verification succeeds; `rejected` if it fails. Call the Create Verification endpoint again to start a new session.",
25111
+ description: "Current verification state. `not_started` before any session has been created; `pending` while a session is in progress and needs the user's input; `processing` while the provider reviews submitted documents \u2014 nothing to do but wait; `action_required` when items in `requested_information` need answers before review can continue; `approved` once verification succeeds; `rejected` if it fails. Call the Create Verification endpoint again to start a new session.",
25024
25112
  enum: [
25025
25113
  "not_started",
25026
25114
  "pending",
25115
+ "processing",
25027
25116
  "approved",
25028
25117
  "rejected",
25029
25118
  "action_required"
@@ -25945,14 +26034,14 @@ var native_spec_default = {
25945
26034
  ]
25946
26035
  },
25947
26036
  impact_score: {
25948
- description: "Estimated revenue impact from 0-100, comparable across accounts, or `null` when not ranked",
26037
+ description: "Estimated impact from 0-100, or `null` when not ranked",
25949
26038
  type: [
25950
26039
  "integer",
25951
26040
  "null"
25952
26041
  ]
25953
26042
  },
25954
26043
  reasoning: {
25955
- description: "Why this action was recommended for this account, or `null`",
26044
+ description: "Why this action was recommended, or `null`",
25956
26045
  type: [
25957
26046
  "string",
25958
26047
  "null"
@@ -26298,6 +26387,10 @@ var native_spec_default = {
26298
26387
  description: "Whop pixel-attributed custom (merchant-defined) conversion events, last-click, across all custom event names.",
26299
26388
  type: "number"
26300
26389
  },
26390
+ custom_event_counts: {
26391
+ description: "Whop pixel-attributed custom conversions broken out by merchant-defined event name, last-click, as a { event_name => count } map over the stats window. Empty when no named custom events are attributed. Custom events fired without a name are counted in custom_conversions but omitted here, so these values sum to at most custom_conversions.",
26392
+ type: "object"
26393
+ },
26301
26394
  delivery_status: {
26302
26395
  description: "The current delivery state, mirroring the Delivery column in the ads dashboard. When several states apply at once, the highest-precedence one is returned.",
26303
26396
  enum: [
@@ -26454,6 +26547,13 @@ var native_spec_default = {
26454
26547
  "null"
26455
26548
  ]
26456
26549
  },
26550
+ results: {
26551
+ description: "The Whop pixel-attributed count behind result_event. When a campaign's ad groups optimize different goals there is no single result_event (it is null), and this is instead the sum of each ad group's own attributed results. Null when nothing Whop-attributable is being optimized for.",
26552
+ type: [
26553
+ "number",
26554
+ "null"
26555
+ ]
26556
+ },
26457
26557
  return_on_ad_spend: {
26458
26558
  description: "Purchase value divided by spend, both in USD (a currency-neutral ratio); 0 when there is no spend.",
26459
26559
  type: "number"
@@ -26555,6 +26655,7 @@ var native_spec_default = {
26555
26655
  "reach",
26556
26656
  "result_event",
26557
26657
  "result_event_name",
26658
+ "results",
26558
26659
  "return_on_ad_spend",
26559
26660
  "spend",
26560
26661
  "spend_currency",
@@ -26567,6 +26668,7 @@ var native_spec_default = {
26567
26668
  "viewed_contents",
26568
26669
  "added_to_carts",
26569
26670
  "custom_conversions",
26671
+ "custom_event_counts",
26570
26672
  "id",
26571
26673
  "title",
26572
26674
  "status",
@@ -26742,6 +26844,10 @@ var native_spec_default = {
26742
26844
  description: "Whop pixel-attributed custom (merchant-defined) conversion events, last-click, across all custom event names.",
26743
26845
  type: "number"
26744
26846
  },
26847
+ custom_event_counts: {
26848
+ description: "Whop pixel-attributed custom conversions broken out by merchant-defined event name, last-click, as a { event_name => count } map over the stats window. Empty when no named custom events are attributed. Custom events fired without a name are counted in custom_conversions but omitted here, so these values sum to at most custom_conversions.",
26849
+ type: "object"
26850
+ },
26745
26851
  delivery_status: {
26746
26852
  description: "The current delivery state, mirroring the Delivery column in the ads dashboard. When several states apply at once, the highest-precedence one is returned.",
26747
26853
  enum: [
@@ -26857,6 +26963,13 @@ var native_spec_default = {
26857
26963
  "null"
26858
26964
  ]
26859
26965
  },
26966
+ results: {
26967
+ description: "The Whop pixel-attributed count behind result_event. When a campaign's ad groups optimize different goals there is no single result_event (it is null), and this is instead the sum of each ad group's own attributed results. Null when nothing Whop-attributable is being optimized for.",
26968
+ type: [
26969
+ "number",
26970
+ "null"
26971
+ ]
26972
+ },
26860
26973
  return_on_ad_spend: {
26861
26974
  description: "Purchase value divided by spend, both in USD (a currency-neutral ratio); 0 when there is no spend.",
26862
26975
  type: "number"
@@ -26958,6 +27071,7 @@ var native_spec_default = {
26958
27071
  "reach",
26959
27072
  "result_event",
26960
27073
  "result_event_name",
27074
+ "results",
26961
27075
  "return_on_ad_spend",
26962
27076
  "spend",
26963
27077
  "spend_currency",
@@ -26970,6 +27084,7 @@ var native_spec_default = {
26970
27084
  "viewed_contents",
26971
27085
  "added_to_carts",
26972
27086
  "custom_conversions",
27087
+ "custom_event_counts",
26973
27088
  "id",
26974
27089
  "title",
26975
27090
  "status",
@@ -27246,6 +27361,10 @@ var native_spec_default = {
27246
27361
  description: "Whop pixel-attributed custom (merchant-defined) conversion events, last-click, across all custom event names.",
27247
27362
  type: "number"
27248
27363
  },
27364
+ custom_event_counts: {
27365
+ description: "Whop pixel-attributed custom conversions broken out by merchant-defined event name, last-click, as a { event_name => count } map over the stats window. Empty when no named custom events are attributed. Custom events fired without a name are counted in custom_conversions but omitted here, so these values sum to at most custom_conversions.",
27366
+ type: "object"
27367
+ },
27249
27368
  delivery_status: {
27250
27369
  description: "The current delivery state, mirroring the Delivery column in the ads dashboard. When several states apply at once, the highest-precedence one is returned.",
27251
27370
  enum: [
@@ -27404,6 +27523,13 @@ var native_spec_default = {
27404
27523
  "null"
27405
27524
  ]
27406
27525
  },
27526
+ results: {
27527
+ description: "The Whop pixel-attributed count behind result_event. When a campaign's ad groups optimize different goals there is no single result_event (it is null), and this is instead the sum of each ad group's own attributed results. Null when nothing Whop-attributable is being optimized for.",
27528
+ type: [
27529
+ "number",
27530
+ "null"
27531
+ ]
27532
+ },
27407
27533
  return_on_ad_spend: {
27408
27534
  description: "Purchase value divided by spend, both in USD (a currency-neutral ratio); 0 when there is no spend.",
27409
27535
  type: "number"
@@ -27493,6 +27619,7 @@ var native_spec_default = {
27493
27619
  "reach",
27494
27620
  "result_event",
27495
27621
  "result_event_name",
27622
+ "results",
27496
27623
  "return_on_ad_spend",
27497
27624
  "spend",
27498
27625
  "spend_currency",
@@ -27505,6 +27632,7 @@ var native_spec_default = {
27505
27632
  "viewed_contents",
27506
27633
  "added_to_carts",
27507
27634
  "custom_conversions",
27635
+ "custom_event_counts",
27508
27636
  "id",
27509
27637
  "title",
27510
27638
  "status",
@@ -27574,8 +27702,8 @@ var native_spec_default = {
27574
27702
  Audience: {
27575
27703
  properties: {
27576
27704
  created_at: {
27577
- description: "Unix timestamp when the audience was created.",
27578
- type: "number"
27705
+ description: "When the audience was created, as an ISO 8601 timestamp.",
27706
+ type: "string"
27579
27707
  },
27580
27708
  error_message: {
27581
27709
  description: "Processing error message. `null` unless processing is partial or failed.",
@@ -27588,6 +27716,13 @@ var native_spec_default = {
27588
27716
  description: "Audience ID, prefixed `adaud_`.",
27589
27717
  type: "string"
27590
27718
  },
27719
+ match_rates: {
27720
+ items: {
27721
+ $ref: "#/components/schemas/AudienceMatchRate",
27722
+ description: "Estimated match rates by ad platform. Empty when the audience was not sent to a supported platform."
27723
+ },
27724
+ type: "array"
27725
+ },
27591
27726
  matched_rows: {
27592
27727
  description: "Rows successfully uploaded to connected ad accounts.",
27593
27728
  type: "number"
@@ -27628,8 +27763,8 @@ var native_spec_default = {
27628
27763
  type: "number"
27629
27764
  },
27630
27765
  updated_at: {
27631
- description: "Unix timestamp when the audience was last updated.",
27632
- type: "number"
27766
+ description: "When the audience was last updated, as an ISO 8601 timestamp.",
27767
+ type: "string"
27633
27768
  }
27634
27769
  },
27635
27770
  required: [
@@ -27643,7 +27778,55 @@ var native_spec_default = {
27643
27778
  "error_message",
27644
27779
  "platform_audience_ids",
27645
27780
  "created_at",
27646
- "updated_at"
27781
+ "updated_at",
27782
+ "match_rates"
27783
+ ],
27784
+ type: "object"
27785
+ },
27786
+ AudienceMatchRate: {
27787
+ properties: {
27788
+ lower_bound: {
27789
+ description: "Lower bound of the estimated match rate percentage. `null` until available.",
27790
+ type: [
27791
+ "number",
27792
+ "null"
27793
+ ]
27794
+ },
27795
+ platform: {
27796
+ description: "The ad platform that provided the match-rate estimate.",
27797
+ enum: [
27798
+ "meta"
27799
+ ],
27800
+ example: "meta",
27801
+ type: "string"
27802
+ },
27803
+ status: {
27804
+ description: "Availability of the estimated match rate.",
27805
+ enum: [
27806
+ "calculating",
27807
+ "available",
27808
+ "unavailable",
27809
+ null
27810
+ ],
27811
+ example: "calculating",
27812
+ type: [
27813
+ "string",
27814
+ "null"
27815
+ ]
27816
+ },
27817
+ upper_bound: {
27818
+ description: "Upper bound of the estimated match rate percentage. `null` until available.",
27819
+ type: [
27820
+ "number",
27821
+ "null"
27822
+ ]
27823
+ }
27824
+ },
27825
+ required: [
27826
+ "platform",
27827
+ "status",
27828
+ "lower_bound",
27829
+ "upper_bound"
27647
27830
  ],
27648
27831
  type: "object"
27649
27832
  },
@@ -29355,6 +29538,14 @@ var native_spec_default = {
29355
29538
  items: {
29356
29539
  description: "Represents an image attachment",
29357
29540
  properties: {
29541
+ content_type: {
29542
+ description: "Uploaded file MIME type, such as image/jpeg, video/mp4, or audio/mpeg.",
29543
+ example: "image/jpeg",
29544
+ type: [
29545
+ "string",
29546
+ "null"
29547
+ ]
29548
+ },
29358
29549
  id: {
29359
29550
  description: 'Represents a unique identifier that is Base64 obfuscated. It is often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"VXNlci0xMA=="`) or integer (such as `4`) input value will be accepted as an ID.',
29360
29551
  type: "string"
@@ -29370,7 +29561,8 @@ var native_spec_default = {
29370
29561
  },
29371
29562
  required: [
29372
29563
  "id",
29373
- "url"
29564
+ "url",
29565
+ "content_type"
29374
29566
  ],
29375
29567
  type: "object"
29376
29568
  },
@@ -29526,6 +29718,7 @@ var native_spec_default = {
29526
29718
  "published_reviews_count",
29527
29719
  "external_identifier",
29528
29720
  "metadata",
29721
+ "gallery_images",
29529
29722
  "description",
29530
29723
  "custom_cta",
29531
29724
  "custom_cta_url",
@@ -29534,7 +29727,6 @@ var native_spec_default = {
29534
29727
  "global_affiliate_status",
29535
29728
  "member_affiliate_percentage",
29536
29729
  "member_affiliate_status",
29537
- "gallery_images",
29538
29730
  "product_tax_code",
29539
29731
  "owner_user",
29540
29732
  "company"
@@ -29558,6 +29750,41 @@ var native_spec_default = {
29558
29750
  "null"
29559
29751
  ]
29560
29752
  },
29753
+ gallery_images: {
29754
+ description: "The gallery images for this product, ordered by position.",
29755
+ items: {
29756
+ description: "Represents an image attachment",
29757
+ properties: {
29758
+ content_type: {
29759
+ description: "Uploaded file MIME type, such as image/jpeg, video/mp4, or audio/mpeg.",
29760
+ example: "image/jpeg",
29761
+ type: [
29762
+ "string",
29763
+ "null"
29764
+ ]
29765
+ },
29766
+ id: {
29767
+ description: 'Represents a unique identifier that is Base64 obfuscated. It is often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"VXNlci0xMA=="`) or integer (such as `4`) input value will be accepted as an ID.',
29768
+ type: "string"
29769
+ },
29770
+ url: {
29771
+ description: "A pre-optimized URL for rendering this attachment on the client. This should be used for displaying attachments in apps.",
29772
+ example: "https://media.whop.com/abc123/optimized.jpg",
29773
+ type: [
29774
+ "string",
29775
+ "null"
29776
+ ]
29777
+ }
29778
+ },
29779
+ required: [
29780
+ "id",
29781
+ "url",
29782
+ "content_type"
29783
+ ],
29784
+ type: "object"
29785
+ },
29786
+ type: "array"
29787
+ },
29561
29788
  headline: {
29562
29789
  description: "A short marketing headline displayed prominently on the product's product page.",
29563
29790
  example: "Real-time data analytics for creators",
@@ -29626,7 +29853,8 @@ var native_spec_default = {
29626
29853
  "route",
29627
29854
  "published_reviews_count",
29628
29855
  "external_identifier",
29629
- "metadata"
29856
+ "metadata",
29857
+ "gallery_images"
29630
29858
  ],
29631
29859
  type: "object"
29632
29860
  },
@@ -29686,12 +29914,18 @@ var native_spec_default = {
29686
29914
  type: "array"
29687
29915
  },
29688
29916
  url: {
29689
- description: "The URL where the social account can be accessed on the platform.",
29690
- type: "string"
29917
+ description: "The URL where the social account can be accessed on the platform. Null while a Whop-owned page is still being provisioned.",
29918
+ type: [
29919
+ "string",
29920
+ "null"
29921
+ ]
29691
29922
  },
29692
29923
  username: {
29693
- description: "The username of the social account on the platform.",
29694
- type: "string"
29924
+ description: "The username of the social account on the platform. Null while a Whop-owned page is still being provisioned.",
29925
+ type: [
29926
+ "string",
29927
+ "null"
29928
+ ]
29695
29929
  },
29696
29930
  verified: {
29697
29931
  description: "Whether the social account is verified on the platform.",
@@ -29861,6 +30095,13 @@ var native_spec_default = {
29861
30095
  verification: {
29862
30096
  description: "Identity verification status for the user's `individual` (KYC) and `business` (KYB) profiles. Each is `null` until created, otherwise a `status` of `not_started`, `pending`, `approved`, or `rejected`.",
29863
30097
  type: "object"
30098
+ },
30099
+ whop_partner_enabled_at: {
30100
+ description: "When the user became an enrolled Whop Partner, as an ISO 8601 timestamp. `null` if never enrolled.",
30101
+ type: [
30102
+ "string",
30103
+ "null"
30104
+ ]
29864
30105
  }
29865
30106
  },
29866
30107
  required: [
@@ -29873,7 +30114,8 @@ var native_spec_default = {
29873
30114
  "balance",
29874
30115
  "earnings_usd",
29875
30116
  "balance_history",
29876
- "verification"
30117
+ "verification",
30118
+ "whop_partner_enabled_at"
29877
30119
  ],
29878
30120
  type: "object"
29879
30121
  },
@@ -30170,56 +30412,165 @@ var native_spec_default = {
30170
30412
  ],
30171
30413
  type: "object"
30172
30414
  },
30173
- UserSummary: {
30415
+ UserRecommendedAction: {
30174
30416
  properties: {
30175
- id: {
30176
- description: "User ID, prefixed `user_`.",
30177
- type: "string"
30178
- },
30179
- name: {
30180
- description: "Display name.",
30417
+ account_id: {
30418
+ description: "The account (`biz_`) a business recommendation is for, or `null` for personal recommendations",
30181
30419
  type: [
30182
30420
  "string",
30183
30421
  "null"
30184
30422
  ]
30185
30423
  },
30186
- profile_picture: {
30187
- $ref: "#/components/schemas/UserProfilePicture",
30188
- description: "Avatar wrapper; its `url` is always present, using a generated placeholder when the user set no picture."
30424
+ account_name: {
30425
+ description: "The account's display name, or `null`",
30426
+ type: [
30427
+ "string",
30428
+ "null"
30429
+ ]
30189
30430
  },
30190
- username: {
30191
- description: "Public username.",
30431
+ action: {
30432
+ description: "The recommendation; new values may be added, so handle unknown actions gracefully",
30433
+ enum: [
30434
+ "create_business",
30435
+ "become_affiliate",
30436
+ "theme_business",
30437
+ "create_product",
30438
+ "create_plan",
30439
+ "verify_identity",
30440
+ "connect_affiliate_program",
30441
+ "create_promotion",
30442
+ "setup_tracking_pixel",
30443
+ "migrate_from_stripe",
30444
+ "accept_first_payment",
30445
+ "launch_first_ad",
30446
+ "invite_team_member",
30447
+ "enable_tax_collection",
30448
+ "create_card",
30449
+ "join_whop_university",
30450
+ "apply_for_financing"
30451
+ ],
30452
+ example: "create_business",
30192
30453
  type: "string"
30193
- }
30194
- },
30195
- required: [
30196
- "id",
30197
- "username",
30198
- "name",
30199
- "profile_picture"
30200
- ],
30201
- type: "object"
30202
- },
30203
- V1ErrorResponse: {
30204
- properties: {
30205
- error: {
30206
- properties: {
30207
- message: {
30208
- description: "Human-readable error message.",
30209
- type: "string"
30210
- },
30211
- type: {
30212
- description: "Machine-readable error code.",
30213
- type: "string"
30214
- }
30454
+ },
30455
+ blocked_capabilities: {
30456
+ items: {
30457
+ description: "Capabilities this would unlock, or empty",
30458
+ type: "string"
30215
30459
  },
30216
- required: [
30217
- "type",
30218
- "message"
30219
- ],
30220
- type: "object"
30221
- }
30222
- },
30460
+ type: "array"
30461
+ },
30462
+ cta: {
30463
+ description: "The URL the call-to-action links to",
30464
+ type: "string"
30465
+ },
30466
+ cta_label: {
30467
+ description: "Button label",
30468
+ type: "string"
30469
+ },
30470
+ description: {
30471
+ description: "Supporting copy, or empty",
30472
+ type: "string"
30473
+ },
30474
+ icon_url: {
30475
+ description: "Illustration icon URL, or `null`",
30476
+ type: [
30477
+ "string",
30478
+ "null"
30479
+ ]
30480
+ },
30481
+ impact_score: {
30482
+ description: "Estimated impact from 0-100, or `null` when not ranked",
30483
+ type: [
30484
+ "integer",
30485
+ "null"
30486
+ ]
30487
+ },
30488
+ reasoning: {
30489
+ description: "Why this action was recommended, or `null`",
30490
+ type: [
30491
+ "string",
30492
+ "null"
30493
+ ]
30494
+ },
30495
+ status: {
30496
+ description: "Always optional \u2014 never blocking",
30497
+ enum: [
30498
+ "optional"
30499
+ ],
30500
+ example: "optional",
30501
+ type: "string"
30502
+ },
30503
+ title: {
30504
+ description: "Headline for the recommendation",
30505
+ type: "string"
30506
+ }
30507
+ },
30508
+ required: [
30509
+ "action",
30510
+ "status",
30511
+ "title",
30512
+ "description",
30513
+ "cta_label",
30514
+ "cta",
30515
+ "icon_url",
30516
+ "blocked_capabilities",
30517
+ "reasoning",
30518
+ "impact_score",
30519
+ "account_id",
30520
+ "account_name"
30521
+ ],
30522
+ type: "object"
30523
+ },
30524
+ UserSummary: {
30525
+ properties: {
30526
+ id: {
30527
+ description: "User ID, prefixed `user_`.",
30528
+ type: "string"
30529
+ },
30530
+ name: {
30531
+ description: "Display name.",
30532
+ type: [
30533
+ "string",
30534
+ "null"
30535
+ ]
30536
+ },
30537
+ profile_picture: {
30538
+ $ref: "#/components/schemas/UserProfilePicture",
30539
+ description: "Avatar wrapper; its `url` is always present, using a generated placeholder when the user set no picture."
30540
+ },
30541
+ username: {
30542
+ description: "Public username.",
30543
+ type: "string"
30544
+ }
30545
+ },
30546
+ required: [
30547
+ "id",
30548
+ "username",
30549
+ "name",
30550
+ "profile_picture"
30551
+ ],
30552
+ type: "object"
30553
+ },
30554
+ V1ErrorResponse: {
30555
+ properties: {
30556
+ error: {
30557
+ properties: {
30558
+ message: {
30559
+ description: "Human-readable error message.",
30560
+ type: "string"
30561
+ },
30562
+ type: {
30563
+ description: "Machine-readable error code.",
30564
+ type: "string"
30565
+ }
30566
+ },
30567
+ required: [
30568
+ "type",
30569
+ "message"
30570
+ ],
30571
+ type: "object"
30572
+ }
30573
+ },
30223
30574
  required: [
30224
30575
  "error"
30225
30576
  ],
@@ -35312,7 +35663,7 @@ import { createRequire as createRequire2 } from "module";
35312
35663
  // src/lib/build-info.ts
35313
35664
  var buildChannel = true ? "npm" : "dev";
35314
35665
  var buildTarget = typeof WHOP_CLI_TARGET === "string" ? WHOP_CLI_TARGET : null;
35315
- var buildVersion = true ? "0.8.0" : null;
35666
+ var buildVersion = true ? "0.8.1" : null;
35316
35667
  function isHomebrewPath(execPath, env = process.env) {
35317
35668
  if (/[/\\](Cellar|homebrew|linuxbrew)[/\\]/.test(execPath)) return true;
35318
35669
  const prefix = env.HOMEBREW_PREFIX?.trim();
@@ -35550,59 +35901,84 @@ function errorHtml(error) {
35550
35901
  // src/auth/callback-server.ts
35551
35902
  var CALLBACK_PORT = 13337;
35552
35903
  var LOOPBACK_HOSTS = ["127.0.0.1", "::1"];
35553
- function startCallbackServer(expectedState) {
35554
- return new Promise((resolve5, reject) => {
35555
- const servers = [];
35556
- let settled = false;
35557
- let bindFailures = 0;
35558
- const settle = (run) => {
35559
- if (settled) return;
35560
- settled = true;
35561
- clearTimeout(timeout);
35562
- for (const server of servers) {
35563
- server.close();
35564
- server.closeAllConnections();
35904
+ async function startCallbackServer(expectedState, options = {}) {
35905
+ const servers = [];
35906
+ let settled = false;
35907
+ const result = Promise.withResolvers();
35908
+ const ready = Promise.withResolvers();
35909
+ const closeServers = () => {
35910
+ for (const server of servers) {
35911
+ server.close();
35912
+ server.closeAllConnections();
35913
+ }
35914
+ };
35915
+ let timeout;
35916
+ const settle = (run) => {
35917
+ if (settled) return;
35918
+ settled = true;
35919
+ clearTimeout(timeout);
35920
+ closeServers();
35921
+ run();
35922
+ };
35923
+ let listening = 0;
35924
+ let bindFailures = 0;
35925
+ const hosts = options.hosts ?? LOOPBACK_HOSTS;
35926
+ for (const host of hosts) {
35927
+ const server = createServer((req, res) => {
35928
+ const url = new URL(req.url ?? "/", "http://localhost");
35929
+ if (url.pathname !== "/callback") {
35930
+ res.writeHead(404, { "Content-Type": "text/plain; charset=utf-8" });
35931
+ res.end("Not found");
35932
+ return;
35565
35933
  }
35566
- run();
35567
- };
35568
- const timeout = setTimeout(
35569
- () => settle(
35570
- () => reject(new Error("Timed out waiting for OAuth callback (5 min)."))
35571
- ),
35572
- 5 * 60 * 1e3
35573
- );
35574
- for (const host of LOOPBACK_HOSTS) {
35575
- const server = createServer((req, res) => {
35576
- const url = new URL(req.url ?? "/", "http://localhost");
35577
- if (url.pathname !== "/callback") {
35578
- res.writeHead(404, { "Content-Type": "text/plain; charset=utf-8" });
35579
- res.end("Not found");
35580
- return;
35581
- }
35582
- if (url.searchParams.get("state") !== expectedState) {
35583
- res.writeHead(400, { "Content-Type": "text/plain; charset=utf-8" });
35584
- res.end("Invalid OAuth state");
35585
- return;
35586
- }
35587
- const code = url.searchParams.get("code");
35588
- const error = url.searchParams.get("error");
35589
- res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
35590
- res.end(code ? successHtml : errorHtml(error), () => {
35591
- settle(() => {
35592
- if (code) resolve5(code);
35593
- else
35594
- reject(new Error(`OAuth error: ${error ?? "no code returned"}`));
35595
- });
35934
+ if (url.searchParams.get("state") !== expectedState) {
35935
+ res.writeHead(400, { "Content-Type": "text/plain; charset=utf-8" });
35936
+ res.end("Invalid OAuth state");
35937
+ return;
35938
+ }
35939
+ const code = url.searchParams.get("code");
35940
+ const error = url.searchParams.get("error");
35941
+ res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
35942
+ res.end(code ? successHtml : errorHtml(error), () => {
35943
+ settle(() => {
35944
+ if (code) result.resolve(code);
35945
+ else
35946
+ result.reject(
35947
+ new Error(`OAuth error: ${error ?? "no code returned"}`)
35948
+ );
35596
35949
  });
35597
35950
  });
35598
- server.on("error", (err) => {
35599
- bindFailures += 1;
35600
- if (bindFailures === LOOPBACK_HOSTS.length) settle(() => reject(err));
35951
+ });
35952
+ server.on("listening", () => {
35953
+ listening += 1;
35954
+ if (listening === 1) ready.resolve();
35955
+ });
35956
+ server.on("error", (error) => {
35957
+ bindFailures += 1;
35958
+ if (bindFailures === hosts.length && listening === 0) {
35959
+ settle(() => ready.reject(error));
35960
+ }
35961
+ });
35962
+ server.listen(options.port ?? CALLBACK_PORT, host);
35963
+ servers.push(server);
35964
+ }
35965
+ await ready.promise;
35966
+ timeout = setTimeout(
35967
+ () => settle(
35968
+ () => result.reject(
35969
+ new Error("Timed out waiting for OAuth callback (5 min).")
35970
+ )
35971
+ ),
35972
+ options.timeoutMs ?? 5 * 60 * 1e3
35973
+ );
35974
+ return {
35975
+ result: result.promise,
35976
+ close: () => settle(() => {
35977
+ result.promise.catch(() => {
35601
35978
  });
35602
- server.listen(CALLBACK_PORT, host);
35603
- servers.push(server);
35604
- }
35605
- });
35979
+ result.reject(new Error("OAuth callback listener closed."));
35980
+ })
35981
+ };
35606
35982
  }
35607
35983
 
35608
35984
  // src/auth/prompts.ts
@@ -35930,6 +36306,18 @@ var OAuthError = class extends Error {
35930
36306
  this.name = "OAuthError";
35931
36307
  }
35932
36308
  };
36309
+ var defaultOAuthLoginDependencies = {
36310
+ startCallbackServer,
36311
+ exchangeCode,
36312
+ fetch,
36313
+ listOAuthAccounts,
36314
+ listProfiles,
36315
+ upsertProfile,
36316
+ deriveProfileName,
36317
+ openBrowser,
36318
+ startSpinner,
36319
+ printInfo
36320
+ };
35933
36321
  async function listOAuthAccounts(accessToken, opts = {}) {
35934
36322
  const whop = new Whop2({ apiKey: accessToken, baseURL: apiBaseUrl() });
35935
36323
  const MAX_ACCOUNTS = 1e3;
@@ -35945,11 +36333,11 @@ async function listOAuthAccounts(accessToken, opts = {}) {
35945
36333
  }
35946
36334
  return accounts;
35947
36335
  }
35948
- async function resolveOAuthAccount(accessToken, opts) {
35949
- const s = opts.agent ? null : startSpinner("Loading your business accounts\u2026");
36336
+ async function resolveOAuthAccount(accessToken, opts, dependencies) {
36337
+ const s = opts.agent ? null : dependencies.startSpinner("Loading your business accounts\u2026");
35950
36338
  let accounts;
35951
36339
  try {
35952
- accounts = await listOAuthAccounts(accessToken, {
36340
+ accounts = await dependencies.listOAuthAccounts(accessToken, {
35953
36341
  stopAtId: opts.accountId
35954
36342
  });
35955
36343
  } catch {
@@ -35983,86 +36371,104 @@ async function resolveOAuthAccount(accessToken, opts) {
35983
36371
  s?.stop(`Using ${accounts[0].title}.`);
35984
36372
  return accounts[0];
35985
36373
  }
35986
- if (opts.agent) {
35987
- s?.stop("");
35988
- throw new OAuthError(
35989
- "MULTIPLE_ACCOUNTS",
35990
- `You can manage ${accounts.length} business accounts \u2014 pass --account-id to choose one: ${accounts.map((account) => `${account.id} (${account.title})`).join(", ")}.`
35991
- );
35992
- }
36374
+ if (opts.agent) return null;
35993
36375
  s?.stop(`Found ${accounts.length} business accounts.`);
35994
36376
  return selectAccount(accounts);
35995
36377
  }
35996
- async function performOAuthLogin(input) {
36378
+ async function prepareOAuthLogin(input, dependencies = defaultOAuthLoginDependencies) {
35997
36379
  const { verifier, challenge } = generatePKCE();
35998
36380
  const state = generateState();
35999
36381
  const nonce = generateNonce();
36000
- const authUrl = buildAuthUrl(challenge, state, nonce);
36001
- const s = startSpinner("Opening browser\u2026");
36002
- openBrowser(authUrl);
36003
- s.stop("Waiting for authorization in your browser\u2026");
36004
- printInfo(`If your browser didn't open, visit:
36005
- ${authUrl}`);
36006
- let code;
36382
+ const authorizationUrl = buildAuthUrl(challenge, state, nonce);
36383
+ let callback;
36007
36384
  try {
36008
- code = await startCallbackServer(state);
36009
- } catch (err) {
36385
+ callback = await dependencies.startCallbackServer(state);
36386
+ } catch (error) {
36010
36387
  throw new OAuthError(
36011
36388
  "OAUTH_CALLBACK_FAILED",
36012
- err instanceof Error ? err.message : "OAuth callback failed."
36013
- );
36014
- }
36015
- const s2 = startSpinner("Exchanging authorization code\u2026");
36016
- let tokens;
36017
- try {
36018
- tokens = await exchangeCode(code, verifier);
36019
- s2.stop("Authorized.");
36020
- } catch (err) {
36021
- s2.stop("Token exchange failed.");
36022
- throw new OAuthError(
36023
- "TOKEN_EXCHANGE_FAILED",
36024
- err instanceof Error ? err.message : "Token exchange failed."
36389
+ error instanceof Error ? error.message : "OAuth callback failed."
36025
36390
  );
36026
36391
  }
36027
- const base = oauthBaseUrl();
36028
- let identity = {};
36029
- let accountIdentity = null;
36030
- try {
36031
- const res = await fetch(`${base}/oauth/userinfo`, {
36032
- headers: { Authorization: `Bearer ${tokens.accessToken}` }
36033
- });
36034
- if (res.ok) {
36035
- const info = await res.json();
36036
- identity = { id: info.sub, title: info.name, email: info.email };
36037
- }
36038
- } catch {
36039
- }
36040
- if (!input.deferAccountSelection) {
36041
- accountIdentity = await resolveOAuthAccount(tokens.accessToken, {
36042
- agent: input.agent ?? false,
36043
- accountId: input.accountId
36044
- });
36045
- }
36046
- const name = input.profile ?? deriveProfileName(identity);
36047
- const existed = listProfiles().some((p) => p.name === name);
36048
- const tokenExpiresAt = new Date(
36049
- Date.now() + tokens.expiresIn * 1e3
36050
- ).toISOString();
36051
- const profile = upsertProfile({
36052
- name,
36053
- method: "oauth",
36054
- secret: tokens.refreshToken,
36055
- identity,
36056
- accountIdentity: accountIdentity ?? void 0,
36057
- accessToken: tokens.accessToken,
36058
- tokenExpiresAt
36059
- });
36060
36392
  return {
36061
- profileName: profile.name,
36062
- identity,
36063
- existed
36393
+ authorizationUrl,
36394
+ complete: async () => {
36395
+ let code;
36396
+ try {
36397
+ code = await callback.result;
36398
+ } catch (error) {
36399
+ throw new OAuthError(
36400
+ "OAUTH_CALLBACK_FAILED",
36401
+ error instanceof Error ? error.message : "OAuth callback failed."
36402
+ );
36403
+ }
36404
+ const spinner4 = input.interactive ? dependencies.startSpinner("Exchanging authorization code\u2026") : null;
36405
+ let tokens;
36406
+ try {
36407
+ tokens = await dependencies.exchangeCode(code, verifier);
36408
+ spinner4?.stop("Authorized.");
36409
+ } catch (error) {
36410
+ spinner4?.stop("Token exchange failed.");
36411
+ throw new OAuthError(
36412
+ "TOKEN_EXCHANGE_FAILED",
36413
+ error instanceof Error ? error.message : "Token exchange failed."
36414
+ );
36415
+ }
36416
+ const base = oauthBaseUrl();
36417
+ let identity = {};
36418
+ let accountIdentity = null;
36419
+ try {
36420
+ const response = await dependencies.fetch(`${base}/oauth/userinfo`, {
36421
+ headers: { Authorization: `Bearer ${tokens.accessToken}` }
36422
+ });
36423
+ if (response.ok) {
36424
+ const info = await response.json();
36425
+ identity = { id: info.sub, title: info.name, email: info.email };
36426
+ }
36427
+ } catch {
36428
+ }
36429
+ if (!input.deferAccountSelection) {
36430
+ accountIdentity = await resolveOAuthAccount(
36431
+ tokens.accessToken,
36432
+ { agent: !input.interactive, accountId: input.accountId },
36433
+ dependencies
36434
+ );
36435
+ }
36436
+ const name = input.profile ?? dependencies.deriveProfileName(identity);
36437
+ const existed = dependencies.listProfiles().some((profile2) => profile2.name === name);
36438
+ const tokenExpiresAt = new Date(
36439
+ Date.now() + tokens.expiresIn * 1e3
36440
+ ).toISOString();
36441
+ const profile = dependencies.upsertProfile({
36442
+ name,
36443
+ method: "oauth",
36444
+ secret: tokens.refreshToken,
36445
+ identity,
36446
+ accountIdentity: accountIdentity ?? void 0,
36447
+ accessToken: tokens.accessToken,
36448
+ tokenExpiresAt
36449
+ });
36450
+ return {
36451
+ profileName: profile.name,
36452
+ identity,
36453
+ existed
36454
+ };
36455
+ }
36064
36456
  };
36065
36457
  }
36458
+ async function performOAuthLogin(input, dependencies = defaultOAuthLoginDependencies) {
36459
+ const login = await prepareOAuthLogin(
36460
+ { ...input, interactive: true },
36461
+ dependencies
36462
+ );
36463
+ const spinner4 = dependencies.startSpinner("Opening browser\u2026");
36464
+ dependencies.openBrowser(login.authorizationUrl);
36465
+ spinner4.stop("Waiting for authorization in your browser\u2026");
36466
+ dependencies.printInfo(
36467
+ `If your browser didn't open, visit:
36468
+ ${login.authorizationUrl}`
36469
+ );
36470
+ return login.complete();
36471
+ }
36066
36472
 
36067
36473
  // src/auth/profiles.ts
36068
36474
  var EXPIRY_BUFFER_MS = 6e4;
@@ -36132,7 +36538,12 @@ function upsertProfile(input, env = process.env) {
36132
36538
  (profile2) => profile2.name === input.name
36133
36539
  );
36134
36540
  const isOauth = input.method === "oauth";
36135
- const account = isOauth ? input.accountIdentity : input.identity;
36541
+ const preservedAccount = existing?.method === "oauth" && existing.accountId && existing.userId === input.identity.id ? {
36542
+ id: existing.accountId,
36543
+ title: existing.accountTitle,
36544
+ route: existing.accountRoute
36545
+ } : void 0;
36546
+ const account = isOauth ? input.accountIdentity ?? preservedAccount : input.identity;
36136
36547
  const profile = {
36137
36548
  name: input.name,
36138
36549
  method: input.method,
@@ -36572,7 +36983,7 @@ var groups_default = [
36572
36983
  name: "partners",
36573
36984
  tag: "Partners",
36574
36985
  description: "The users and businesses you referred to Whop, and what you earn from them.",
36575
- group: "Referrals"
36986
+ group: "Partners"
36576
36987
  },
36577
36988
  {
36578
36989
  name: "workforce-bounties",
@@ -36636,8 +37047,10 @@ var groups_default = [
36636
37047
  }
36637
37048
  ];
36638
37049
 
36639
- // src/auth/commands.ts
37050
+ // src/auth/login.ts
37051
+ var LoginMethod = external_exports.enum(["oauth", "api-key"]);
36640
37052
  var loginOptions = external_exports.object({
37053
+ method: LoginMethod.optional().describe("Authentication method to use"),
36641
37054
  apiKey: external_exports.string().optional().describe("API key for non-interactive login (skips the prompt)"),
36642
37055
  profile: external_exports.string().optional().describe("Name for this profile (defaults to the account route)"),
36643
37056
  accountId: external_exports.string().optional().describe(
@@ -36649,104 +37062,78 @@ var loginEnv = external_exports.object({
36649
37062
  WHOP_API_BASE_URL: external_exports.string().optional().describe("Override the Whop API base URL"),
36650
37063
  WHOP_CONFIG_DIR: external_exports.string().optional().describe("Override the CLI config directory")
36651
37064
  });
36652
- var loginOutput = external_exports.object({
37065
+ var authenticatedLoginOutput = external_exports.object({
36653
37066
  profile: external_exports.string().describe("The profile name"),
36654
37067
  active: external_exports.boolean().describe("Whether this profile is now the active one"),
36655
37068
  method: AuthMethod.describe("The authentication method"),
36656
37069
  identity: Identity.describe("The authenticated account or user identity")
36657
37070
  });
36658
- var logoutOptions = external_exports.object({
36659
- profile: external_exports.string().optional().describe("Profile to remove (defaults to the active profile)"),
36660
- all: external_exports.boolean().optional().describe("Remove every profile and its stored secret (full reset)")
36661
- });
36662
- var logoutOutput = external_exports.object({
36663
- removed: external_exports.array(external_exports.string()).describe("The removed profile name(s)"),
36664
- newActive: external_exports.string().nullable().describe("The profile that is now active, if any")
36665
- });
36666
- var statusOutput = external_exports.object({
36667
- loggedIn: external_exports.boolean().describe("Whether the active profile has a usable stored credential"),
36668
- profile: external_exports.string().nullable(),
36669
- method: AuthMethod.nullable(),
36670
- identity: Identity.nullable().describe(
36671
- "The logged-in user (OAuth) or the account (API key)"
36672
- ),
36673
- account: Identity.nullable().describe(
36674
- "The account auto-filled for scoped commands (account_id/company_id)"
36675
- ),
36676
- hasSecret: external_exports.boolean().describe("Whether a secret was found in the OS keychain for this profile")
36677
- });
36678
- var listOutput = external_exports.object({
36679
- active: external_exports.string().nullable(),
36680
- profiles: external_exports.array(Profile)
36681
- });
36682
- var switchArgs = external_exports.object({
36683
- name: external_exports.string().optional().describe("Profile to switch to (interactive picker if omitted)")
36684
- });
36685
- var switchOutput = external_exports.object({
36686
- active: external_exports.string().describe("The newly active profile")
36687
- });
36688
- var accountArgs = external_exports.object({
36689
- id: external_exports.string().optional().describe(
36690
- "Business account to make the default \u2014 id (biz_xxx) or route (interactive picker if omitted)"
36691
- )
36692
- });
36693
- var accountOptions2 = external_exports.object({
36694
- list: external_exports.boolean().optional().describe(
36695
- "List the business accounts you can manage without changing the default"
36696
- )
36697
- });
36698
- var accountListItem = external_exports.object({
36699
- id: external_exports.string(),
36700
- title: external_exports.string(),
36701
- route: external_exports.string(),
36702
- active: external_exports.boolean().describe("Whether this is the profile's default business account")
36703
- });
36704
- var accountOutput = external_exports.object({
36705
- profile: external_exports.string().describe("The active profile"),
36706
- account: Identity.nullable().describe(
36707
- "The default business account passed to scoped commands"
36708
- ),
36709
- accounts: external_exports.array(accountListItem).describe("Business accounts this user can manage")
37071
+ var authorizationRequiredOutput = external_exports.object({
37072
+ type: external_exports.literal("authorization_required"),
37073
+ authorizationUrl: external_exports.string().describe("Open this URL in the user's browser to authorize the CLI")
36710
37074
  });
37075
+ var loginOutput = external_exports.union([
37076
+ authorizationRequiredOutput,
37077
+ authenticatedLoginOutput
37078
+ ]);
36711
37079
  var loginExamples = [
36712
37080
  { description: "Interactive login" },
36713
37081
  {
36714
- options: { apiKey: "whop_xxx" },
36715
- description: "Non-interactive login (CI / agents)"
37082
+ options: { method: "oauth" },
37083
+ description: "Open a browser for OAuth login"
37084
+ },
37085
+ {
37086
+ options: { method: "api-key", apiKey: "whop_xxx" },
37087
+ description: "Non-interactive API-key login"
36716
37088
  },
36717
37089
  {
36718
- options: { apiKey: "whop_xxx", profile: "prod" },
37090
+ options: { method: "api-key", apiKey: "whop_xxx", profile: "prod" },
36719
37091
  description: "Log in and name the profile"
36720
37092
  }
36721
37093
  ];
36722
- var loginHint = "Agents / CI: pass --api-key or set WHOP_API_KEY to skip the prompt.";
37094
+ var loginHint = "Agents: run `login --method oauth --format jsonl` in the background with stdout redirected to a file (pipes like `| head` can buffer past the URL). The first line is an authorization_required event \u2014 open its authorizationUrl in the user's browser yourself (e.g. `open <url>` on macOS, `xdg-open` on Linux). The URL is several KB long, so pass it programmatically and NEVER retype, truncate, or summarize it: a mangled scope list fails with invalid_scope. Then wait for the process to exit; the final done event means the login saved. If the user manages multiple businesses the login still succeeds without one \u2014 set it afterwards with `auth account <biz_id>` (use `auth account --list` to enumerate). For unattended use, pass --api-key or set WHOP_API_KEY instead.";
37095
+ function oauthSuccess(result) {
37096
+ return {
37097
+ ok: true,
37098
+ existed: result.existed,
37099
+ underscoped: false,
37100
+ output: {
37101
+ profile: result.profileName,
37102
+ active: true,
37103
+ method: "oauth",
37104
+ identity: result.identity
37105
+ }
37106
+ };
37107
+ }
37108
+ function oauthFailure(error) {
37109
+ if (error instanceof OAuthError) {
37110
+ return { ok: false, code: error.code, message: error.message };
37111
+ }
37112
+ throw error;
37113
+ }
36723
37114
  async function performLogin(input) {
36724
- let method = "api_key";
36725
- if (!input.agent && !input.apiKey) method = await chooseAuthMethod();
37115
+ let method = input.method === "oauth" ? "oauth" : "api_key";
37116
+ if (!input.method && !input.agent && !input.apiKey) {
37117
+ method = await chooseAuthMethod();
37118
+ }
36726
37119
  if (method === "oauth") {
36727
- try {
36728
- const { profileName, identity: identity2, existed: existed2 } = await performOAuthLogin({
36729
- profile: input.profile,
36730
- agent: input.agent,
36731
- accountId: input.accountId,
36732
- deferAccountSelection: input.deferAccountSelection
36733
- });
37120
+ if (input.agent) {
36734
37121
  return {
36735
- ok: true,
36736
- existed: existed2,
36737
- underscoped: false,
36738
- output: {
36739
- profile: profileName,
36740
- active: true,
36741
- method: "oauth",
36742
- identity: identity2
36743
- }
37122
+ ok: false,
37123
+ code: "OAUTH_STREAMING_REQUIRED",
37124
+ message: "OAuth login in agent mode must stream the authorization URL \u2014 use `login --method oauth --format jsonl`."
36744
37125
  };
36745
- } catch (err) {
36746
- if (err instanceof OAuthError) {
36747
- return { ok: false, code: err.code, message: err.message };
36748
- }
36749
- throw err;
37126
+ }
37127
+ try {
37128
+ return oauthSuccess(
37129
+ await performOAuthLogin({
37130
+ profile: input.profile,
37131
+ accountId: input.accountId,
37132
+ deferAccountSelection: input.deferAccountSelection
37133
+ })
37134
+ );
37135
+ } catch (error) {
37136
+ return oauthFailure(error);
36750
37137
  }
36751
37138
  }
36752
37139
  let apiKey = input.apiKey;
@@ -36791,11 +37178,80 @@ async function performLogin(input) {
36791
37178
  output: { profile: profile.name, active: true, method, identity }
36792
37179
  };
36793
37180
  }
36794
- async function loginAdapter(c2) {
37181
+ function loginSuccessMeta(result) {
37182
+ if (!getActiveProfile()?.accountId) {
37183
+ return {
37184
+ cta: {
37185
+ description: "You're logged in. Choose or create the business the CLI should use:",
37186
+ commands: [
37187
+ {
37188
+ command: "auth account",
37189
+ description: "Set the default business account (--list to see them)"
37190
+ },
37191
+ {
37192
+ command: "quickstart",
37193
+ description: "Choose or create a business account"
37194
+ }
37195
+ ]
37196
+ }
37197
+ };
37198
+ }
37199
+ return {
37200
+ cta: {
37201
+ description: result.existed ? "Updated and switched to this profile:" : "You're logged in:",
37202
+ commands: [
37203
+ { command: "auth status", description: "Show the active identity" },
37204
+ {
37205
+ command: "quickstart",
37206
+ description: "Choose or create a business account"
37207
+ }
37208
+ ]
37209
+ }
37210
+ };
37211
+ }
37212
+ function failLogin(c2, result) {
37213
+ let cta;
37214
+ if (result.code === "API_KEY_REQUIRED") {
37215
+ cta = {
37216
+ description: "Choose a non-interactive login method:",
37217
+ commands: [
37218
+ {
37219
+ command: "auth login",
37220
+ options: { method: "oauth" },
37221
+ description: "Use OAuth (add --format jsonl for agents)"
37222
+ },
37223
+ {
37224
+ command: "auth login",
37225
+ options: { method: "api-key", apiKey: true },
37226
+ description: "Pass --api-key <key>"
37227
+ }
37228
+ ]
37229
+ };
37230
+ } else if (result.code === "ACCOUNT_NOT_FOUND") {
37231
+ cta = {
37232
+ description: "Choose which business account to use:",
37233
+ commands: [
37234
+ {
37235
+ command: "auth login",
37236
+ options: { method: "oauth", accountId: true },
37237
+ description: "Pass --account-id biz_xxx"
37238
+ }
37239
+ ]
37240
+ };
37241
+ }
37242
+ return c2.error({
37243
+ code: result.code,
37244
+ message: result.message,
37245
+ retryable: result.code !== "INVALID_API_KEY",
37246
+ cta
37247
+ });
37248
+ }
37249
+ async function standardLoginAdapter(c2) {
36795
37250
  let result;
36796
37251
  try {
36797
37252
  result = await performLogin({
36798
37253
  agent: c2.agent,
37254
+ method: c2.options.method,
36799
37255
  apiKey: c2.options.apiKey ?? c2.env.WHOP_API_KEY,
36800
37256
  profile: c2.options.profile,
36801
37257
  accountId: c2.options.accountId
@@ -36810,65 +37266,114 @@ async function loginAdapter(c2) {
36810
37266
  }
36811
37267
  throw error;
36812
37268
  }
36813
- if (!result.ok) {
36814
- let cta;
36815
- if (result.code === "API_KEY_REQUIRED") {
36816
- cta = {
36817
- description: "Provide a key non-interactively:",
36818
- commands: [
36819
- {
36820
- command: "auth login",
36821
- options: { apiKey: true },
36822
- description: "Pass --api-key <key>"
36823
- }
36824
- ]
36825
- };
36826
- } else if (result.code === "MULTIPLE_ACCOUNTS" || result.code === "ACCOUNT_NOT_FOUND") {
36827
- cta = {
36828
- description: "Choose which business account to use:",
36829
- commands: [
36830
- {
36831
- command: "auth login",
36832
- options: { accountId: true },
36833
- description: "Pass --account-id biz_xxx"
36834
- }
36835
- ]
36836
- };
36837
- }
36838
- return c2.error({
36839
- code: result.code,
36840
- message: result.message,
36841
- retryable: result.code !== "INVALID_API_KEY",
36842
- cta
36843
- });
37269
+ if (!result.ok) return failLogin(c2, result);
37270
+ return c2.ok(result.output, loginSuccessMeta(result));
37271
+ }
37272
+ async function* streamingOAuthLoginAdapter(c2, oauthDependencies) {
37273
+ let login;
37274
+ try {
37275
+ login = await prepareOAuthLogin(
37276
+ {
37277
+ profile: c2.options.profile,
37278
+ interactive: false,
37279
+ accountId: c2.options.accountId
37280
+ },
37281
+ oauthDependencies
37282
+ );
37283
+ } catch (error) {
37284
+ return failLogin(c2, oauthFailure(error));
36844
37285
  }
36845
- const accountId = getActiveProfile()?.accountId;
36846
- if (!accountId) {
36847
- return c2.ok(result.output, {
36848
- cta: {
36849
- description: "You're logged in. Choose or create the business the CLI should use:",
36850
- commands: [
36851
- {
36852
- command: "quickstart",
36853
- description: "Choose or create a business account"
36854
- }
36855
- ]
36856
- }
37286
+ yield {
37287
+ type: "authorization_required",
37288
+ authorizationUrl: login.authorizationUrl
37289
+ };
37290
+ let result;
37291
+ try {
37292
+ result = oauthSuccess(await login.complete());
37293
+ } catch (error) {
37294
+ return failLogin(c2, oauthFailure(error));
37295
+ }
37296
+ yield result.output;
37297
+ return c2.ok(result.output, loginSuccessMeta(result));
37298
+ }
37299
+ function loginAdapter(c2, oauthDependencies) {
37300
+ if (c2.options.method === "oauth" && c2.options.apiKey) {
37301
+ return c2.error({
37302
+ code: "CONFLICTING_OPTIONS",
37303
+ message: "--method oauth cannot be combined with --api-key.",
37304
+ retryable: true
36857
37305
  });
36858
37306
  }
36859
- return c2.ok(result.output, {
36860
- cta: {
36861
- description: result.existed ? "Updated and switched to this profile:" : "You're logged in:",
36862
- commands: [
36863
- { command: "auth status", description: "Show the active identity" },
36864
- {
36865
- command: "quickstart",
36866
- description: "Choose or create a business account"
37307
+ if (c2.options.method === "oauth" && (c2.agent || c2.format === "jsonl")) {
37308
+ if (c2.formatExplicit && c2.format !== "jsonl") {
37309
+ return c2.error({
37310
+ code: "OAUTH_STREAMING_FORMAT_REQUIRED",
37311
+ message: "OAuth login requires --format jsonl so the authorization URL is shown before the callback wait.",
37312
+ retryable: true,
37313
+ cta: {
37314
+ commands: ["auth login --method oauth --format jsonl"]
36867
37315
  }
36868
- ]
37316
+ });
36869
37317
  }
36870
- });
37318
+ return streamingOAuthLoginAdapter(c2, oauthDependencies);
37319
+ }
37320
+ return standardLoginAdapter(c2);
36871
37321
  }
37322
+
37323
+ // src/auth/commands.ts
37324
+ var logoutOptions = external_exports.object({
37325
+ profile: external_exports.string().optional().describe("Profile to remove (defaults to the active profile)"),
37326
+ all: external_exports.boolean().optional().describe("Remove every profile and its stored secret (full reset)")
37327
+ });
37328
+ var logoutOutput = external_exports.object({
37329
+ removed: external_exports.array(external_exports.string()).describe("The removed profile name(s)"),
37330
+ newActive: external_exports.string().nullable().describe("The profile that is now active, if any")
37331
+ });
37332
+ var statusOutput = external_exports.object({
37333
+ loggedIn: external_exports.boolean().describe("Whether the active profile has a usable stored credential"),
37334
+ profile: external_exports.string().nullable(),
37335
+ method: AuthMethod.nullable(),
37336
+ identity: Identity.nullable().describe(
37337
+ "The logged-in user (OAuth) or the account (API key)"
37338
+ ),
37339
+ account: Identity.nullable().describe(
37340
+ "The account auto-filled for scoped commands (account_id/company_id)"
37341
+ ),
37342
+ hasSecret: external_exports.boolean().describe("Whether a secret was found in the OS keychain for this profile")
37343
+ });
37344
+ var listOutput = external_exports.object({
37345
+ active: external_exports.string().nullable(),
37346
+ profiles: external_exports.array(Profile)
37347
+ });
37348
+ var switchArgs = external_exports.object({
37349
+ name: external_exports.string().optional().describe("Profile to switch to (interactive picker if omitted)")
37350
+ });
37351
+ var switchOutput = external_exports.object({
37352
+ active: external_exports.string().describe("The newly active profile")
37353
+ });
37354
+ var accountArgs = external_exports.object({
37355
+ id: external_exports.string().optional().describe(
37356
+ "Business account to make the default \u2014 id (biz_xxx) or route (interactive picker if omitted)"
37357
+ )
37358
+ });
37359
+ var accountOptions2 = external_exports.object({
37360
+ list: external_exports.boolean().optional().describe(
37361
+ "List the business accounts you can manage without changing the default"
37362
+ )
37363
+ });
37364
+ var accountListItem = external_exports.object({
37365
+ id: external_exports.string(),
37366
+ title: external_exports.string(),
37367
+ route: external_exports.string(),
37368
+ active: external_exports.boolean().describe("Whether this is the profile's default business account")
37369
+ });
37370
+ var accountOutput = external_exports.object({
37371
+ profile: external_exports.string().describe("The active profile"),
37372
+ account: Identity.nullable().describe(
37373
+ "The default business account passed to scoped commands"
37374
+ ),
37375
+ accounts: external_exports.array(accountListItem).describe("Business accounts this user can manage")
37376
+ });
36872
37377
  function logoutAdapter(c2) {
36873
37378
  if (c2.options.all) {
36874
37379
  if (c2.options.profile) {
@@ -38961,7 +39466,7 @@ ${c.success("\u2713")} ${action} business account ${chalk3.bold(`"${title}"`)} $
38961
39466
  // package.json
38962
39467
  var package_default = {
38963
39468
  name: "@whop/cli",
38964
- version: "0.8.0",
39469
+ version: "0.8.1",
38965
39470
  description: "The Whop CLI \u2014 build and manage Whop apps from your terminal. Human and agent friendly.",
38966
39471
  keywords: [
38967
39472
  "agent",