@scalemule/nextjs 0.0.35 → 0.0.37

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.mjs CHANGED
@@ -288,78 +288,6 @@ var init_upload_compression_VOUJRAIM = __esm({
288
288
 
289
289
  // node_modules/@scalemule/sdk/dist/index.mjs
290
290
  init_chunk_3FTGBRLU();
291
-
292
- // node_modules/@scalemule/ui/dist/phone/index.mjs
293
- var PHONE_COUNTRIES = [
294
- { code: "US", name: "United States", dialCode: "+1" },
295
- { code: "CA", name: "Canada", dialCode: "+1" },
296
- { code: "GB", name: "United Kingdom", dialCode: "+44" },
297
- { code: "AU", name: "Australia", dialCode: "+61" },
298
- { code: "DE", name: "Germany", dialCode: "+49" },
299
- { code: "FR", name: "France", dialCode: "+33" },
300
- { code: "IT", name: "Italy", dialCode: "+39" },
301
- { code: "ES", name: "Spain", dialCode: "+34" },
302
- { code: "NL", name: "Netherlands", dialCode: "+31" },
303
- { code: "BE", name: "Belgium", dialCode: "+32" },
304
- { code: "CH", name: "Switzerland", dialCode: "+41" },
305
- { code: "AT", name: "Austria", dialCode: "+43" },
306
- { code: "SE", name: "Sweden", dialCode: "+46" },
307
- { code: "NO", name: "Norway", dialCode: "+47" },
308
- { code: "DK", name: "Denmark", dialCode: "+45" },
309
- { code: "FI", name: "Finland", dialCode: "+358" },
310
- { code: "IE", name: "Ireland", dialCode: "+353" },
311
- { code: "PT", name: "Portugal", dialCode: "+351" },
312
- { code: "PL", name: "Poland", dialCode: "+48" },
313
- { code: "CZ", name: "Czech Republic", dialCode: "+420" },
314
- { code: "GR", name: "Greece", dialCode: "+30" },
315
- { code: "RU", name: "Russia", dialCode: "+7" },
316
- { code: "JP", name: "Japan", dialCode: "+81" },
317
- { code: "KR", name: "South Korea", dialCode: "+82" },
318
- { code: "CN", name: "China", dialCode: "+86" },
319
- { code: "HK", name: "Hong Kong", dialCode: "+852" },
320
- { code: "TW", name: "Taiwan", dialCode: "+886" },
321
- { code: "SG", name: "Singapore", dialCode: "+65" },
322
- { code: "MY", name: "Malaysia", dialCode: "+60" },
323
- { code: "TH", name: "Thailand", dialCode: "+66" },
324
- { code: "VN", name: "Vietnam", dialCode: "+84" },
325
- { code: "PH", name: "Philippines", dialCode: "+63" },
326
- { code: "ID", name: "Indonesia", dialCode: "+62" },
327
- { code: "IN", name: "India", dialCode: "+91" },
328
- { code: "PK", name: "Pakistan", dialCode: "+92" },
329
- { code: "BD", name: "Bangladesh", dialCode: "+880" },
330
- { code: "AE", name: "UAE", dialCode: "+971" },
331
- { code: "SA", name: "Saudi Arabia", dialCode: "+966" },
332
- { code: "IL", name: "Israel", dialCode: "+972" },
333
- { code: "TR", name: "Turkey", dialCode: "+90" },
334
- { code: "EG", name: "Egypt", dialCode: "+20" },
335
- { code: "ZA", name: "South Africa", dialCode: "+27" },
336
- { code: "NG", name: "Nigeria", dialCode: "+234" },
337
- { code: "KE", name: "Kenya", dialCode: "+254" },
338
- { code: "BR", name: "Brazil", dialCode: "+55" },
339
- { code: "MX", name: "Mexico", dialCode: "+52" },
340
- { code: "AR", name: "Argentina", dialCode: "+54" },
341
- { code: "CL", name: "Chile", dialCode: "+56" },
342
- { code: "CO", name: "Colombia", dialCode: "+57" },
343
- { code: "PE", name: "Peru", dialCode: "+51" },
344
- { code: "NZ", name: "New Zealand", dialCode: "+64" }
345
- ];
346
- function normalizePhoneNumber(input) {
347
- if (typeof input !== "string") return "";
348
- const trimmed = input.trim();
349
- if (!trimmed) return "";
350
- const digitsOnly = trimmed.replace(/\D/g, "");
351
- if (!digitsOnly) return "";
352
- if (trimmed.startsWith("+")) {
353
- return `+${digitsOnly}`;
354
- }
355
- if (trimmed.startsWith("00") && digitsOnly.length > 2) {
356
- return `+${digitsOnly.slice(2)}`;
357
- }
358
- return `+${digitsOnly}`;
359
- }
360
- [...PHONE_COUNTRIES].sort((a, b) => b.dialCode.length - a.dialCode.length);
361
-
362
- // node_modules/@scalemule/sdk/dist/index.mjs
363
291
  function buildClientContextHeaders(context) {
364
292
  if (!context) return {};
365
293
  const headers = {};
@@ -384,6 +312,7 @@ var WORKSPACE_STORAGE_KEY = "scalemule_workspace_id";
384
312
  var ANONYMOUS_ID_STORAGE_KEY = "scalemule_anonymous_id";
385
313
  var SESSION_POOL_KEY = "scalemule_session_pool";
386
314
  var ACTIVE_ACCOUNT_KEY = "scalemule_active_account";
315
+ var KNOWN_ACCOUNTS_KEY = "scalemule_known_accounts";
387
316
  var GATEWAY_URLS = {
388
317
  dev: "https://api-dev.scalemule.com",
389
318
  prod: "https://api.scalemule.com"
@@ -433,6 +362,54 @@ function statusToErrorCode(status) {
433
362
  return status >= 500 ? "internal_error" : `http_${status}`;
434
363
  }
435
364
  }
365
+ var MAX_KNOWN_ACCOUNTS = 10;
366
+ function maskEmail(email) {
367
+ const parts = email.split("@");
368
+ const local = parts[0] ?? "";
369
+ const domain = parts[1];
370
+ if (!domain) return "***@***.***";
371
+ const tldDot = domain.lastIndexOf(".");
372
+ const tld = tldDot > 0 ? domain.slice(tldDot) : "";
373
+ const domainBase = tldDot > 0 ? domain.slice(0, tldDot) : domain;
374
+ return `${local[0] || "*"}***@${domainBase[0] || "*"}***${tld}`;
375
+ }
376
+ function stableColorIndex(userId) {
377
+ let hash = 0;
378
+ for (let i = 0; i < userId.length; i++) {
379
+ hash = (hash << 5) - hash + userId.charCodeAt(i) | 0;
380
+ }
381
+ return Math.abs(hash) % 8;
382
+ }
383
+ function applyPrivacy(account, privacy) {
384
+ switch (privacy) {
385
+ case "full":
386
+ return {
387
+ userId: account.userId,
388
+ email: account.email,
389
+ fullName: account.fullName,
390
+ avatarUrl: account.avatarUrl,
391
+ provider: account.provider,
392
+ lastActiveAt: account.lastActiveAt
393
+ };
394
+ case "masked":
395
+ return {
396
+ userId: account.userId,
397
+ email: account.email ? maskEmail(account.email) : void 0,
398
+ fullName: account.fullName && account.fullName.length > 0 ? `${account.fullName[0].toUpperCase()}.` : void 0,
399
+ provider: account.provider,
400
+ lastActiveAt: account.lastActiveAt,
401
+ colorIndex: stableColorIndex(account.userId)
402
+ };
403
+ case "minimal":
404
+ return {
405
+ userId: account.userId,
406
+ provider: account.provider,
407
+ lastActiveAt: account.lastActiveAt,
408
+ displayLabel: "Account",
409
+ colorIndex: stableColorIndex(account.userId)
410
+ };
411
+ }
412
+ }
436
413
  function createDefaultStorage() {
437
414
  if (typeof window !== "undefined" && window.localStorage) {
438
415
  return {
@@ -579,6 +556,7 @@ var ScaleMuleClient = class {
579
556
  this.workspaceId = null;
580
557
  this.anonymousId = null;
581
558
  this.sessionPool = /* @__PURE__ */ new Map();
559
+ this.knownAccounts = /* @__PURE__ */ new Map();
582
560
  this.apiKey = config.apiKey;
583
561
  this.applicationId = config.applicationId || null;
584
562
  this.baseUrl = config.baseUrl || GATEWAY_URLS[config.environment || "prod"];
@@ -595,6 +573,8 @@ var ScaleMuleClient = class {
595
573
  this.offlineQueue.setOnlineCallback(() => this.syncOfflineQueue());
596
574
  }
597
575
  this.multiSessionEnabled = config.enableMultiSession || false;
576
+ this.accountSwitcherEnabled = config.enableAccountSwitcher || false;
577
+ this.accountSwitcherPrivacy = config.accountSwitcherPrivacy || "full";
598
578
  }
599
579
  // --------------------------------------------------------------------------
600
580
  // Session Management
@@ -637,6 +617,27 @@ var ScaleMuleClient = class {
637
617
  this.userId = activeId;
638
618
  }
639
619
  }
620
+ if (this.accountSwitcherEnabled) {
621
+ const knownJson = await this.storage.getItem(KNOWN_ACCOUNTS_KEY);
622
+ if (knownJson) {
623
+ try {
624
+ const entries = JSON.parse(knownJson);
625
+ this.knownAccounts = new Map(Object.entries(entries));
626
+ let changed = false;
627
+ for (const [userId2, entry] of this.knownAccounts) {
628
+ const normalized = applyPrivacy(entry, this.accountSwitcherPrivacy);
629
+ if (JSON.stringify(normalized) !== JSON.stringify(entry)) {
630
+ this.knownAccounts.set(userId2, normalized);
631
+ changed = true;
632
+ }
633
+ }
634
+ if (changed) {
635
+ await this.persistKnownAccounts();
636
+ }
637
+ } catch {
638
+ }
639
+ }
640
+ }
640
641
  if (this.debug)
641
642
  console.log(
642
643
  "[ScaleMule] Initialized, session:",
@@ -644,7 +645,9 @@ var ScaleMuleClient = class {
644
645
  "anonymousId:",
645
646
  anonId,
646
647
  "poolSize:",
647
- this.sessionPool.size
648
+ this.sessionPool.size,
649
+ "knownAccounts:",
650
+ this.knownAccounts.size
648
651
  );
649
652
  }
650
653
  async setSession(token, userId) {
@@ -768,6 +771,57 @@ var ScaleMuleClient = class {
768
771
  }
769
772
  await this.storage.setItem(SESSION_POOL_KEY, JSON.stringify(obj));
770
773
  }
774
+ // --------------------------------------------------------------------------
775
+ // Account Switcher (Secure — metadata only, no tokens)
776
+ // --------------------------------------------------------------------------
777
+ isAccountSwitcherEnabled() {
778
+ return this.accountSwitcherEnabled;
779
+ }
780
+ getAccountSwitcherPrivacy() {
781
+ return this.accountSwitcherPrivacy;
782
+ }
783
+ /** Get all known accounts that have logged in on this device (privacy-transformed) */
784
+ getKnownAccounts() {
785
+ return Array.from(this.knownAccounts.values());
786
+ }
787
+ /**
788
+ * Record an account as "known" on this device.
789
+ * Applies privacy transforms before storing — full email is never persisted
790
+ * in masked/minimal modes. Evicts oldest accounts if over the cap.
791
+ * Called automatically after successful login/register when account switcher is enabled.
792
+ */
793
+ async addKnownAccount(account) {
794
+ const display = applyPrivacy(account, this.accountSwitcherPrivacy);
795
+ this.knownAccounts.set(account.userId, display);
796
+ if (this.knownAccounts.size > MAX_KNOWN_ACCOUNTS) {
797
+ const sorted = Array.from(this.knownAccounts.entries()).sort(
798
+ (a, b) => (a[1].lastActiveAt || "").localeCompare(b[1].lastActiveAt || "")
799
+ );
800
+ while (this.knownAccounts.size > MAX_KNOWN_ACCOUNTS && sorted.length > 0) {
801
+ const oldest = sorted.shift();
802
+ this.knownAccounts.delete(oldest[0]);
803
+ }
804
+ }
805
+ await this.persistKnownAccounts();
806
+ }
807
+ /** Remove a specific account from the known accounts list ("forget this account") */
808
+ async removeKnownAccount(userId) {
809
+ this.knownAccounts.delete(userId);
810
+ await this.persistKnownAccounts();
811
+ }
812
+ /** Clear all known accounts ("forget all accounts on this device") */
813
+ async clearKnownAccounts() {
814
+ this.knownAccounts.clear();
815
+ await this.storage.removeItem(KNOWN_ACCOUNTS_KEY);
816
+ }
817
+ /** Persist known accounts to storage */
818
+ async persistKnownAccounts() {
819
+ const obj = {};
820
+ for (const [k, v] of this.knownAccounts) {
821
+ obj[k] = v;
822
+ }
823
+ await this.storage.setItem(KNOWN_ACCOUNTS_KEY, JSON.stringify(obj));
824
+ }
771
825
  getBaseUrl() {
772
826
  return this.baseUrl;
773
827
  }
@@ -1259,6 +1313,74 @@ function asString(parent, key) {
1259
1313
  const value = parent[key];
1260
1314
  return typeof value === "string" ? value : void 0;
1261
1315
  }
1316
+ var PHONE_COUNTRIES = [
1317
+ { code: "US", name: "United States", dialCode: "+1" },
1318
+ { code: "CA", name: "Canada", dialCode: "+1" },
1319
+ { code: "GB", name: "United Kingdom", dialCode: "+44" },
1320
+ { code: "AU", name: "Australia", dialCode: "+61" },
1321
+ { code: "DE", name: "Germany", dialCode: "+49" },
1322
+ { code: "FR", name: "France", dialCode: "+33" },
1323
+ { code: "IT", name: "Italy", dialCode: "+39" },
1324
+ { code: "ES", name: "Spain", dialCode: "+34" },
1325
+ { code: "NL", name: "Netherlands", dialCode: "+31" },
1326
+ { code: "BE", name: "Belgium", dialCode: "+32" },
1327
+ { code: "CH", name: "Switzerland", dialCode: "+41" },
1328
+ { code: "AT", name: "Austria", dialCode: "+43" },
1329
+ { code: "SE", name: "Sweden", dialCode: "+46" },
1330
+ { code: "NO", name: "Norway", dialCode: "+47" },
1331
+ { code: "DK", name: "Denmark", dialCode: "+45" },
1332
+ { code: "FI", name: "Finland", dialCode: "+358" },
1333
+ { code: "IE", name: "Ireland", dialCode: "+353" },
1334
+ { code: "PT", name: "Portugal", dialCode: "+351" },
1335
+ { code: "PL", name: "Poland", dialCode: "+48" },
1336
+ { code: "CZ", name: "Czech Republic", dialCode: "+420" },
1337
+ { code: "GR", name: "Greece", dialCode: "+30" },
1338
+ { code: "RU", name: "Russia", dialCode: "+7" },
1339
+ { code: "JP", name: "Japan", dialCode: "+81" },
1340
+ { code: "KR", name: "South Korea", dialCode: "+82" },
1341
+ { code: "CN", name: "China", dialCode: "+86" },
1342
+ { code: "HK", name: "Hong Kong", dialCode: "+852" },
1343
+ { code: "TW", name: "Taiwan", dialCode: "+886" },
1344
+ { code: "SG", name: "Singapore", dialCode: "+65" },
1345
+ { code: "MY", name: "Malaysia", dialCode: "+60" },
1346
+ { code: "TH", name: "Thailand", dialCode: "+66" },
1347
+ { code: "VN", name: "Vietnam", dialCode: "+84" },
1348
+ { code: "PH", name: "Philippines", dialCode: "+63" },
1349
+ { code: "ID", name: "Indonesia", dialCode: "+62" },
1350
+ { code: "IN", name: "India", dialCode: "+91" },
1351
+ { code: "PK", name: "Pakistan", dialCode: "+92" },
1352
+ { code: "BD", name: "Bangladesh", dialCode: "+880" },
1353
+ { code: "AE", name: "UAE", dialCode: "+971" },
1354
+ { code: "SA", name: "Saudi Arabia", dialCode: "+966" },
1355
+ { code: "IL", name: "Israel", dialCode: "+972" },
1356
+ { code: "TR", name: "Turkey", dialCode: "+90" },
1357
+ { code: "EG", name: "Egypt", dialCode: "+20" },
1358
+ { code: "ZA", name: "South Africa", dialCode: "+27" },
1359
+ { code: "NG", name: "Nigeria", dialCode: "+234" },
1360
+ { code: "KE", name: "Kenya", dialCode: "+254" },
1361
+ { code: "BR", name: "Brazil", dialCode: "+55" },
1362
+ { code: "MX", name: "Mexico", dialCode: "+52" },
1363
+ { code: "AR", name: "Argentina", dialCode: "+54" },
1364
+ { code: "CL", name: "Chile", dialCode: "+56" },
1365
+ { code: "CO", name: "Colombia", dialCode: "+57" },
1366
+ { code: "PE", name: "Peru", dialCode: "+51" },
1367
+ { code: "NZ", name: "New Zealand", dialCode: "+64" }
1368
+ ];
1369
+ function normalizePhoneNumber(input) {
1370
+ if (typeof input !== "string") return "";
1371
+ const trimmed = input.trim();
1372
+ if (!trimmed) return "";
1373
+ const digitsOnly = trimmed.replace(/\D/g, "");
1374
+ if (!digitsOnly) return "";
1375
+ if (trimmed.startsWith("+")) {
1376
+ return `+${digitsOnly}`;
1377
+ }
1378
+ if (trimmed.startsWith("00") && digitsOnly.length > 2) {
1379
+ return `+${digitsOnly.slice(2)}`;
1380
+ }
1381
+ return `+${digitsOnly}`;
1382
+ }
1383
+ [...PHONE_COUNTRIES].sort((a, b) => b.dialCode.length - a.dialCode.length);
1262
1384
  function collectDeviceFingerprint() {
1263
1385
  if (typeof window === "undefined" || typeof navigator === "undefined") return void 0;
1264
1386
  try {
@@ -1387,6 +1509,16 @@ var AuthService = class extends ServiceModule {
1387
1509
  addedAt: (/* @__PURE__ */ new Date()).toISOString()
1388
1510
  });
1389
1511
  }
1512
+ if (result.data && this.client.isAccountSwitcherEnabled()) {
1513
+ await this.client.addKnownAccount({
1514
+ userId: result.data.user.id,
1515
+ email: result.data.user.email,
1516
+ fullName: result.data.user.full_name,
1517
+ avatarUrl: result.data.user.avatar_url,
1518
+ provider: "email",
1519
+ lastActiveAt: (/* @__PURE__ */ new Date()).toISOString()
1520
+ });
1521
+ }
1390
1522
  return result;
1391
1523
  }
1392
1524
  async login(data, options) {
@@ -1407,6 +1539,16 @@ var AuthService = class extends ServiceModule {
1407
1539
  addedAt: (/* @__PURE__ */ new Date()).toISOString()
1408
1540
  });
1409
1541
  }
1542
+ if (result.data && this.client.isAccountSwitcherEnabled()) {
1543
+ await this.client.addKnownAccount({
1544
+ userId: result.data.user.id,
1545
+ email: result.data.user.email,
1546
+ fullName: result.data.user.full_name,
1547
+ avatarUrl: result.data.user.avatar_url,
1548
+ provider: "email",
1549
+ lastActiveAt: (/* @__PURE__ */ new Date()).toISOString()
1550
+ });
1551
+ }
1410
1552
  return result;
1411
1553
  }
1412
1554
  async logout(options) {
@@ -1548,7 +1690,18 @@ var AuthService = class extends ServiceModule {
1548
1690
  }
1549
1691
  async handleOAuthCallback(data, options) {
1550
1692
  const { provider, ...rest } = data;
1551
- return this._get(this.withQuery(`/oauth/${provider}/callback`, rest), options);
1693
+ const result = await this._get(this.withQuery(`/oauth/${provider}/callback`, rest), options);
1694
+ if (result.data && this.client.isAccountSwitcherEnabled()) {
1695
+ await this.client.addKnownAccount({
1696
+ userId: result.data.user.id,
1697
+ email: result.data.user.email,
1698
+ fullName: result.data.user.full_name,
1699
+ avatarUrl: result.data.user.avatar_url,
1700
+ provider,
1701
+ lastActiveAt: (/* @__PURE__ */ new Date()).toISOString()
1702
+ });
1703
+ }
1704
+ return result;
1552
1705
  }
1553
1706
  async listOAuthProviders(options) {
1554
1707
  return this._get("/oauth/providers", options);
@@ -5249,6 +5402,71 @@ var FlagContentService = class extends ServiceModule {
5249
5402
  return this._get(`/appeals/${id}`, options);
5250
5403
  }
5251
5404
  };
5405
+ var CreatorMakerService = class extends ServiceModule {
5406
+ constructor() {
5407
+ super(...arguments);
5408
+ this.basePath = "/v1/creator-maker";
5409
+ }
5410
+ /** Submit a generation job. */
5411
+ async generate(data, options) {
5412
+ return this.post("/jobs", data, options);
5413
+ }
5414
+ /** Get a generation job by ID. */
5415
+ async getJob(jobId, options) {
5416
+ return this._get(`/jobs/${jobId}`, options);
5417
+ }
5418
+ /** Long-poll for job completion (server holds up to 30s). */
5419
+ async pollJob(jobId, options) {
5420
+ return this._get(`/jobs/${jobId}/poll`, {
5421
+ ...options,
5422
+ timeout: 35e3
5423
+ });
5424
+ }
5425
+ /** List the current user's generation jobs. */
5426
+ async listJobs(params, options) {
5427
+ return this._list("/jobs", params, options);
5428
+ }
5429
+ /** Cancel a pending or queued job. */
5430
+ async cancelJob(jobId, options) {
5431
+ return this.post(`/jobs/${jobId}/cancel`, void 0, options);
5432
+ }
5433
+ /** Retry a failed job. */
5434
+ async retryJob(jobId, options) {
5435
+ return this.post(`/jobs/${jobId}/retry`, void 0, options);
5436
+ }
5437
+ /** Generate variations of a completed job. */
5438
+ async generateVariations(jobId, options) {
5439
+ return this.post(`/jobs/${jobId}/variations`, void 0, options);
5440
+ }
5441
+ /** List available style presets, optionally filtered by mode. */
5442
+ async listPresets(params, options) {
5443
+ return this._get(this.withQuery("/presets", params), options);
5444
+ }
5445
+ /** Get a style preset by slug. */
5446
+ async getPreset(slug, options) {
5447
+ return this._get(`/presets/${slug}`, options);
5448
+ }
5449
+ /** Create a project. */
5450
+ async createProject(data, options) {
5451
+ return this.post("/projects", data, options);
5452
+ }
5453
+ /** List the current user's projects. */
5454
+ async listProjects(params, options) {
5455
+ return this._list("/projects", params, options);
5456
+ }
5457
+ /** Get generation usage and credit balance. */
5458
+ async getUsage(options) {
5459
+ return this._get("/usage", options);
5460
+ }
5461
+ /** Get a generation output by ID. */
5462
+ async getOutput(outputId, options) {
5463
+ return this._get(`/outputs/${outputId}`, options);
5464
+ }
5465
+ /** Get a download URL for a generation output. */
5466
+ async getDownloadUrl(outputId, options) {
5467
+ return this._get(`/outputs/${outputId}/download`, options);
5468
+ }
5469
+ };
5252
5470
  var AgentAuthService = class extends ServiceModule {
5253
5471
  constructor() {
5254
5472
  super(...arguments);
@@ -5450,6 +5668,13 @@ var AgentProjectsService = class extends ServiceModule {
5450
5668
  options
5451
5669
  );
5452
5670
  }
5671
+ async startTask(taskId, agentId, applicationId, options) {
5672
+ return this.post(
5673
+ this.withAppId(`/tasks/${taskId}/start`, applicationId),
5674
+ { agent_id: agentId },
5675
+ options
5676
+ );
5677
+ }
5453
5678
  async submit(taskId, data, applicationId, options) {
5454
5679
  return this.post(this.withAppId(`/tasks/${taskId}/submit`, applicationId), data, options);
5455
5680
  }
@@ -5748,6 +5973,7 @@ var ScaleMule = class {
5748
5973
  this.functions = new FunctionsService(this._client);
5749
5974
  this.photo = new PhotoService(this._client);
5750
5975
  this.flagContent = new FlagContentService(this._client);
5976
+ this.creatorMaker = new CreatorMakerService(this._client);
5751
5977
  this.compliance = new ComplianceService(this._client);
5752
5978
  this.orchestrator = new OrchestratorService(this._client);
5753
5979
  this.agentAuth = new AgentAuthService(this._client);
@@ -5827,6 +6053,36 @@ var ScaleMule = class {
5827
6053
  async clearAllAccounts() {
5828
6054
  return this._client.clearAllAccounts();
5829
6055
  }
6056
+ // --------------------------------------------------------------------------
6057
+ // Account Switcher (Secure — metadata only, re-auth required)
6058
+ // --------------------------------------------------------------------------
6059
+ /** Whether the account switcher is enabled */
6060
+ isAccountSwitcherEnabled() {
6061
+ return this._client.isAccountSwitcherEnabled();
6062
+ }
6063
+ /** The configured privacy level for the account switcher */
6064
+ getAccountSwitcherPrivacy() {
6065
+ return this._client.getAccountSwitcherPrivacy();
6066
+ }
6067
+ /**
6068
+ * Get all accounts that have previously logged in on this device.
6069
+ * Returns privacy-transformed display data — no raw PII in masked/minimal modes.
6070
+ * Requires `enableAccountSwitcher: true` in config.
6071
+ */
6072
+ getKnownAccounts() {
6073
+ return this._client.getKnownAccounts();
6074
+ }
6075
+ /**
6076
+ * Forget a specific account — removes it from the known accounts list.
6077
+ * Does NOT affect any active session.
6078
+ */
6079
+ async removeKnownAccount(userId) {
6080
+ return this._client.removeKnownAccount(userId);
6081
+ }
6082
+ /** Forget all known accounts on this device. */
6083
+ async clearKnownAccounts() {
6084
+ return this._client.clearKnownAccounts();
6085
+ }
5830
6086
  /** The base URL being used for API requests. */
5831
6087
  getBaseUrl() {
5832
6088
  return this._client.getBaseUrl();
@@ -6658,6 +6914,8 @@ function ScaleMuleProvider({
6658
6914
  analyticsProxyUrl,
6659
6915
  authProxyUrl,
6660
6916
  publishableKey,
6917
+ enableAccountSwitcher,
6918
+ accountSwitcherPrivacy,
6661
6919
  children,
6662
6920
  onLogin,
6663
6921
  onLogout,
@@ -6795,9 +7053,11 @@ function ScaleMuleProvider({
6795
7053
  publishableKey,
6796
7054
  gatewayUrl: gatewayUrl || (environment === "dev" ? "https://api-dev.scalemule.com" : "https://api.scalemule.com"),
6797
7055
  environment: environment || void 0,
7056
+ enableAccountSwitcher,
7057
+ accountSwitcherPrivacy,
6798
7058
  bootstrapFlags
6799
7059
  }),
6800
- [client, baseClient, user, handleSetUser, initializing, error, analyticsProxyUrl, authProxyUrl, publishableKey, gatewayUrl, environment, bootstrapFlags]
7060
+ [client, baseClient, user, handleSetUser, initializing, error, analyticsProxyUrl, authProxyUrl, publishableKey, gatewayUrl, environment, enableAccountSwitcher, accountSwitcherPrivacy, bootstrapFlags]
6801
7061
  );
6802
7062
  return /* @__PURE__ */ jsx(ScaleMuleContext.Provider, { value, children });
6803
7063
  }
@@ -6814,6 +7074,41 @@ function useScaleMuleClient() {
6814
7074
  const { client } = useScaleMule();
6815
7075
  return client;
6816
7076
  }
7077
+ function maskEmail2(email) {
7078
+ const [local, domain] = email.split("@");
7079
+ if (!domain) return "***@***.***";
7080
+ const tldDot = domain.lastIndexOf(".");
7081
+ const tld = tldDot > 0 ? domain.slice(tldDot) : "";
7082
+ const domainBase = tldDot > 0 ? domain.slice(0, tldDot) : domain;
7083
+ return `${local[0] || "*"}***@${domainBase[0] || "*"}***${tld}`;
7084
+ }
7085
+ function stableColorIndex2(userId) {
7086
+ let hash = 0;
7087
+ for (let i = 0; i < userId.length; i++) {
7088
+ hash = (hash << 5) - hash + userId.charCodeAt(i) | 0;
7089
+ }
7090
+ return Math.abs(hash) % 8;
7091
+ }
7092
+ function applyClientPrivacy(entry, privacy) {
7093
+ if (!privacy || privacy === "full") return entry;
7094
+ if (privacy === "masked") {
7095
+ return {
7096
+ userId: entry.userId,
7097
+ email: entry.email ? maskEmail2(entry.email) : void 0,
7098
+ fullName: entry.fullName ? `${entry.fullName[0].toUpperCase()}.` : void 0,
7099
+ provider: entry.provider,
7100
+ lastActiveAt: entry.lastActiveAt,
7101
+ colorIndex: stableColorIndex2(entry.userId)
7102
+ };
7103
+ }
7104
+ return {
7105
+ userId: entry.userId,
7106
+ provider: entry.provider,
7107
+ lastActiveAt: entry.lastActiveAt,
7108
+ displayLabel: "Account",
7109
+ colorIndex: stableColorIndex2(entry.userId)
7110
+ };
7111
+ }
6817
7112
  function getCookie(name) {
6818
7113
  if (typeof document === "undefined") return void 0;
6819
7114
  const match = document.cookie.match(new RegExp(`(?:^|; )${name}=([^;]*)`));
@@ -6842,7 +7137,7 @@ async function proxyFetch(proxyUrl, path, options = {}) {
6842
7137
  return data;
6843
7138
  }
6844
7139
  function useAuth() {
6845
- const { client, user, setUser, initializing, error, setError, authProxyUrl } = useScaleMule();
7140
+ const { client, user, setUser, initializing, error, setError, authProxyUrl, enableAccountSwitcher, accountSwitcherPrivacy } = useScaleMule();
6846
7141
  const register = useCallback(
6847
7142
  async (data) => {
6848
7143
  setError(null);
@@ -7450,6 +7745,63 @@ function useAuth() {
7450
7745
  },
7451
7746
  [client, setUser, setError, authProxyUrl]
7452
7747
  );
7748
+ const readKnownAccountsCookie = useCallback(() => {
7749
+ if (!enableAccountSwitcher) return [];
7750
+ if (typeof document === "undefined") return [];
7751
+ const match = document.cookie.match(/(?:^|; )sm_known_accounts=([^;]*)/);
7752
+ if (!match) return [];
7753
+ try {
7754
+ const decoded = decodeURIComponent(match[1]);
7755
+ const accounts = JSON.parse(decoded);
7756
+ let entries = Object.values(accounts);
7757
+ if (accountSwitcherPrivacy && accountSwitcherPrivacy !== "full") {
7758
+ entries = entries.map((e) => applyClientPrivacy(e, accountSwitcherPrivacy));
7759
+ }
7760
+ return entries;
7761
+ } catch {
7762
+ return [];
7763
+ }
7764
+ }, [enableAccountSwitcher, accountSwitcherPrivacy]);
7765
+ const [knownAccounts, setKnownAccounts] = useState([]);
7766
+ useEffect(() => {
7767
+ setKnownAccounts(readKnownAccountsCookie());
7768
+ }, [readKnownAccountsCookie, user]);
7769
+ const switchAccount = useCallback(
7770
+ async (userId) => {
7771
+ const target = knownAccounts.find((a) => a.userId === userId) || null;
7772
+ if (!target) return null;
7773
+ if (authProxyUrl) {
7774
+ await proxyFetch(authProxyUrl, "switch-account");
7775
+ } else {
7776
+ const sessionToken = client.getSessionToken();
7777
+ if (sessionToken) {
7778
+ try {
7779
+ await client.post("/v1/auth/logout", { session_token: sessionToken });
7780
+ } catch {
7781
+ }
7782
+ }
7783
+ await client.clearSession();
7784
+ }
7785
+ setUser(null);
7786
+ return target;
7787
+ },
7788
+ [client, setUser, knownAccounts, authProxyUrl]
7789
+ );
7790
+ const removeKnownAccount = useCallback(
7791
+ async (userId) => {
7792
+ if (authProxyUrl) {
7793
+ await proxyFetch(authProxyUrl, "forget-account", { body: { user_id: userId } });
7794
+ }
7795
+ setKnownAccounts((prev) => prev.filter((a) => a.userId !== userId));
7796
+ },
7797
+ [authProxyUrl]
7798
+ );
7799
+ const clearKnownAccounts = useCallback(async () => {
7800
+ if (authProxyUrl) {
7801
+ await proxyFetch(authProxyUrl, "forget-all-accounts");
7802
+ }
7803
+ setKnownAccounts([]);
7804
+ }, [authProxyUrl]);
7453
7805
  return useMemo(
7454
7806
  () => ({
7455
7807
  user,
@@ -7481,7 +7833,12 @@ function useAuth() {
7481
7833
  // Phone auth
7482
7834
  sendPhoneCode,
7483
7835
  verifyPhone,
7484
- loginWithPhone
7836
+ loginWithPhone,
7837
+ // Account switcher
7838
+ knownAccounts,
7839
+ switchAccount,
7840
+ removeKnownAccount,
7841
+ clearKnownAccounts
7485
7842
  }),
7486
7843
  [
7487
7844
  user,
@@ -7508,7 +7865,11 @@ function useAuth() {
7508
7865
  regenerateBackupCodes,
7509
7866
  sendPhoneCode,
7510
7867
  verifyPhone,
7511
- loginWithPhone
7868
+ loginWithPhone,
7869
+ knownAccounts,
7870
+ switchAccount,
7871
+ removeKnownAccount,
7872
+ clearKnownAccounts
7512
7873
  ]
7513
7874
  );
7514
7875
  }