@anuma/sdk 6.31.0 → 6.31.2

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.
@@ -21859,14 +21859,14 @@ async function autoFilterClientTools(clientTools, promptEmbeddings, cache, embed
21859
21859
  const alwaysInclude = clientTools.filter(isAlwaysIncluded);
21860
21860
  const filterCandidates = clientTools.filter((t) => !isAlwaysIncluded(t));
21861
21861
  if (filterCandidates.length === 0) {
21862
- return { tools: clientTools, activatedSetNames: /* @__PURE__ */ new Set() };
21862
+ return { tools: clientTools, activatedSetNames: /* @__PURE__ */ new Set(), matchedSetNames: /* @__PURE__ */ new Set() };
21863
21863
  }
21864
21864
  if (!promptEmbeddings && noEmbeddingsReason === "error") {
21865
- return { tools: clientTools, activatedSetNames: /* @__PURE__ */ new Set() };
21865
+ return { tools: clientTools, activatedSetNames: /* @__PURE__ */ new Set(), matchedSetNames: /* @__PURE__ */ new Set() };
21866
21866
  }
21867
21867
  if (!promptEmbeddings) {
21868
21868
  if (activeToolSets.length === 0) {
21869
- return { tools: [], activatedSetNames: /* @__PURE__ */ new Set() };
21869
+ return { tools: [], activatedSetNames: /* @__PURE__ */ new Set(), matchedSetNames: /* @__PURE__ */ new Set() };
21870
21870
  }
21871
21871
  const allSets = extraToolSets.length > 0 ? [...BUILT_IN_TOOL_SETS, ...extraToolSets] : BUILT_IN_TOOL_SETS;
21872
21872
  const activeSets = allSets.filter((s) => activeToolSets.includes(s.name));
@@ -21876,7 +21876,8 @@ async function autoFilterClientTools(clientTools, promptEmbeddings, cache, embed
21876
21876
  ...alwaysInclude,
21877
21877
  ...filterCandidates.filter((t) => stickyMembers.has(getToolName2(t)))
21878
21878
  ],
21879
- activatedSetNames: new Set(activeSets.map((s) => s.name))
21879
+ activatedSetNames: new Set(activeSets.map((s) => s.name)),
21880
+ matchedSetNames: /* @__PURE__ */ new Set()
21880
21881
  };
21881
21882
  }
21882
21883
  const toolsNeedingEmbeddings = [];
@@ -21894,7 +21895,7 @@ async function autoFilterClientTools(clientTools, promptEmbeddings, cache, embed
21894
21895
  cache.set(toolsNeedingEmbeddings[i].name, embeddings[i]);
21895
21896
  }
21896
21897
  } catch {
21897
- return { tools: clientTools, activatedSetNames: /* @__PURE__ */ new Set() };
21898
+ return { tools: clientTools, activatedSetNames: /* @__PURE__ */ new Set(), matchedSetNames: /* @__PURE__ */ new Set() };
21898
21899
  }
21899
21900
  }
21900
21901
  const pseudoServerTools = [];
@@ -21940,15 +21941,170 @@ async function autoFilterClientTools(clientTools, promptEmbeddings, cache, embed
21940
21941
  activeSetNames
21941
21942
  );
21942
21943
  const activatedSetNames = activatedToolSetNames(scores, toolSets, activeSetNames);
21944
+ const matchedSetNames = activatedToolSetNames(scores, toolSets);
21943
21945
  if (finalNames.size === 0) {
21944
- return { tools: alwaysInclude, activatedSetNames };
21946
+ return { tools: alwaysInclude, activatedSetNames, matchedSetNames };
21945
21947
  }
21946
21948
  const filtered = filterCandidates.filter((t) => {
21947
21949
  const name = getToolName2(t);
21948
21950
  return name && finalNames.has(name);
21949
21951
  });
21950
- return { tools: [...alwaysInclude, ...filtered], activatedSetNames };
21952
+ return { tools: [...alwaysInclude, ...filtered], activatedSetNames, matchedSetNames };
21953
+ }
21954
+
21955
+ // src/lib/tools/toolCatalog.ts
21956
+ var TOOL_CATALOG = {
21957
+ // Gmail (src/tools/gmail.ts)
21958
+ gmail_search_messages: { label: "Search emails", provider: "gmail", connector: "Gmail" },
21959
+ gmail_get_message: { label: "Read an email", provider: "gmail", connector: "Gmail" },
21960
+ gmail_create_draft: { label: "Draft a reply", provider: "gmail", connector: "Gmail" },
21961
+ gmail_send_message: { label: "Send an email", provider: "gmail", connector: "Gmail" },
21962
+ // Google Calendar (src/tools/googleCalendar.ts)
21963
+ google_calendar_list_events: {
21964
+ label: "Search calendar events",
21965
+ provider: "gcalendar",
21966
+ connector: "Calendar"
21967
+ },
21968
+ google_calendar_create_event: {
21969
+ label: "Create calendar event",
21970
+ provider: "gcalendar",
21971
+ connector: "Calendar"
21972
+ },
21973
+ google_calendar_update_event: {
21974
+ label: "Update calendar event",
21975
+ provider: "gcalendar",
21976
+ connector: "Calendar"
21977
+ },
21978
+ // Google Drive (src/tools/googleDrive.ts)
21979
+ google_drive_search: { label: "Search files", provider: "gdrive", connector: "Drive" },
21980
+ google_drive_list_recent: { label: "List recent files", provider: "gdrive", connector: "Drive" },
21981
+ google_drive_get_content: { label: "Read file content", provider: "gdrive", connector: "Drive" },
21982
+ google_drive_create_file: {
21983
+ label: "Create a file in Drive",
21984
+ provider: "gdrive",
21985
+ connector: "Drive"
21986
+ },
21987
+ google_drive_update_file: {
21988
+ label: "Update a Drive file",
21989
+ provider: "gdrive",
21990
+ connector: "Drive"
21991
+ },
21992
+ // Notion (src/tools/notion.ts)
21993
+ "notion-search": { label: "Search", provider: "notion", connector: "Notion" },
21994
+ "notion-fetch": { label: "Read page", provider: "notion", connector: "Notion" },
21995
+ "notion-create-pages": { label: "Create page", provider: "notion", connector: "Notion" },
21996
+ "notion-update-page": { label: "Update page", provider: "notion", connector: "Notion" },
21997
+ "notion-move-pages": { label: "Move pages", provider: "notion", connector: "Notion" },
21998
+ "notion-duplicate-page": { label: "Duplicate page", provider: "notion", connector: "Notion" },
21999
+ "notion-create-database": { label: "Create database", provider: "notion", connector: "Notion" },
22000
+ "notion-update-data-source": {
22001
+ label: "Update data source",
22002
+ provider: "notion",
22003
+ connector: "Notion"
22004
+ },
22005
+ "notion-create-comment": { label: "Add a comment", provider: "notion", connector: "Notion" },
22006
+ "notion-get-comments": { label: "Read comments", provider: "notion", connector: "Notion" },
22007
+ "notion-get-users": {
22008
+ label: "List workspace members",
22009
+ provider: "notion",
22010
+ connector: "Notion"
22011
+ },
22012
+ "notion-get-teams": { label: "List teamspaces", provider: "notion", connector: "Notion" },
22013
+ // GitHub (src/tools/github.ts)
22014
+ github_api: { label: "Use GitHub", provider: "github", connector: "GitHub" },
22015
+ github_get_authenticated_user: {
22016
+ label: "Read GitHub profile",
22017
+ provider: "github",
22018
+ connector: "GitHub"
22019
+ },
22020
+ // X / Twitter (src/tools/x.ts)
22021
+ x_get_me: { label: "Get my X profile", provider: "x", connector: "X" },
22022
+ x_get_my_posts: { label: "Read my recent posts", provider: "x", connector: "X" },
22023
+ // Dropbox (src/tools/dropbox.ts)
22024
+ dropbox_list_folders: { label: "List files", provider: "dropbox", connector: "Dropbox" },
22025
+ dropbox_get_file_content: {
22026
+ label: "Read file content",
22027
+ provider: "dropbox",
22028
+ connector: "Dropbox"
22029
+ },
22030
+ dropbox_search: { label: "Search files", provider: "dropbox", connector: "Dropbox" },
22031
+ // Slack (src/tools/slack.ts)
22032
+ slack_get_me: { label: "Get my Slack profile", provider: "slack", connector: "Slack" },
22033
+ slack_list_channels: { label: "List channels", provider: "slack", connector: "Slack" },
22034
+ slack_list_dms: { label: "List direct messages", provider: "slack", connector: "Slack" },
22035
+ slack_search_messages: { label: "Search messages", provider: "slack", connector: "Slack" },
22036
+ slack_list_users: { label: "List members", provider: "slack", connector: "Slack" },
22037
+ slack_get_channel_history: {
22038
+ label: "Read channel history",
22039
+ provider: "slack",
22040
+ connector: "Slack"
22041
+ },
22042
+ slack_get_thread_replies: {
22043
+ label: "Read thread replies",
22044
+ provider: "slack",
22045
+ connector: "Slack"
22046
+ },
22047
+ slack_post_message: { label: "Post a message", provider: "slack", connector: "Slack" }
22048
+ };
22049
+
22050
+ // src/lib/tools/selection/activeToolSets.ts
22051
+ function mergeActiveToolSets(current, derived) {
22052
+ if (derived.length === 0) return current;
22053
+ const merged = Array.from(/* @__PURE__ */ new Set([...current, ...derived]));
22054
+ return merged.length === current.length ? current : merged;
22055
+ }
22056
+
22057
+ // src/lib/tools/selection/recentToolSets.ts
22058
+ var RECENT_TOOL_SET_TURNS = 2;
22059
+ var RECENT_TOOL_SET_CONVERSATION_LIMIT = 50;
22060
+ var CARRYABLE_TOOL_SETS = new Set(
22061
+ BUILT_IN_TOOL_SETS.filter(
22062
+ (s) => s.anchors.length > 0 && s.anchors.every((a) => a in TOOL_CATALOG)
22063
+ ).map((s) => s.name)
22064
+ );
22065
+ var recentToolSets = /* @__PURE__ */ new WeakMap();
22066
+ function touch(conversations, conversationId) {
22067
+ const turns = conversations.get(conversationId);
22068
+ if (!turns) return void 0;
22069
+ conversations.delete(conversationId);
22070
+ conversations.set(conversationId, turns);
22071
+ return turns;
22072
+ }
22073
+ function carriedToolSets(database, conversationId) {
22074
+ if (!conversationId) return [];
22075
+ const conversations = recentToolSets.get(database);
22076
+ if (!conversations) return [];
22077
+ return [...touch(conversations, conversationId)?.keys() ?? []];
22078
+ }
22079
+ function recordToolSetTurn(database, conversationId, matched) {
22080
+ if (!conversationId) return;
22081
+ let conversations = recentToolSets.get(database);
22082
+ if (!conversations) {
22083
+ conversations = /* @__PURE__ */ new Map();
22084
+ recentToolSets.set(database, conversations);
22085
+ }
22086
+ const turns = touch(conversations, conversationId) ?? /* @__PURE__ */ new Map();
22087
+ for (const [name, left] of turns) {
22088
+ if (left > 1) turns.set(name, left - 1);
22089
+ else turns.delete(name);
22090
+ }
22091
+ for (const name of matched) {
22092
+ if (CARRYABLE_TOOL_SETS.has(name)) turns.set(name, RECENT_TOOL_SET_TURNS);
22093
+ }
22094
+ if (turns.size === 0) {
22095
+ conversations.delete(conversationId);
22096
+ return;
22097
+ }
22098
+ conversations.set(conversationId, turns);
22099
+ if (conversations.size > RECENT_TOOL_SET_CONVERSATION_LIMIT) {
22100
+ const oldest = conversations.keys().next().value;
22101
+ if (oldest !== void 0) conversations.delete(oldest);
22102
+ }
22103
+ }
22104
+ function resetRecentToolSets() {
22105
+ recentToolSets = /* @__PURE__ */ new WeakMap();
21951
22106
  }
22107
+ onClearAllEncryptionState(resetRecentToolSets);
21952
22108
 
21953
22109
  // src/react/useChatMedia.ts
21954
22110
  import { useCallback as useCallback3 } from "react";
@@ -23380,6 +23536,8 @@ function useChatStorage(options) {
23380
23536
  }
23381
23537
  let filteredClientTools2 = clientTools;
23382
23538
  let clientActivatedSetNames2;
23539
+ let matchedToolSets2 = /* @__PURE__ */ new Set();
23540
+ const toolSetConversationId = explicitConversationId ?? currentConversationId;
23383
23541
  if (clientToolsFilter && clientTools?.length) {
23384
23542
  if (!skipStorageEmbeddingsFailed) {
23385
23543
  const clientToolNames = clientToolsFilter(skipStorageEmbeddings, clientTools);
@@ -23396,11 +23554,15 @@ function useChatStorage(options) {
23396
23554
  clientToolEmbeddingsCacheRef.current,
23397
23555
  { getToken, baseUrl, model: embeddingModel },
23398
23556
  extraToolSets,
23399
- activeToolSetsRef.current,
23557
+ mergeActiveToolSets(
23558
+ activeToolSetsRef.current ?? [],
23559
+ carriedToolSets(database, toolSetConversationId)
23560
+ ),
23400
23561
  skipStorageEmbeddingsFailed ? "error" : "short-prompt"
23401
23562
  );
23402
23563
  filteredClientTools2 = clientFilterResult.tools;
23403
23564
  clientActivatedSetNames2 = clientFilterResult.activatedSetNames;
23565
+ matchedToolSets2 = clientFilterResult.matchedSetNames;
23404
23566
  }
23405
23567
  if (filteredServerTools2.length > 0 || filteredClientTools2 && filteredClientTools2.length > 0) {
23406
23568
  mergedTools2 = mergeTools(
@@ -23455,6 +23617,7 @@ function useChatStorage(options) {
23455
23617
  error: result2.error || "Unknown error"
23456
23618
  };
23457
23619
  }
23620
+ recordToolSetTurn(database, toolSetConversationId, matchedToolSets2);
23458
23621
  const refreshResponse = result2.data;
23459
23622
  if (getToken) {
23460
23623
  Promise.resolve().then(
@@ -23835,6 +23998,7 @@ function useChatStorage(options) {
23835
23998
  }
23836
23999
  let filteredClientTools = clientTools;
23837
24000
  let clientActivatedSetNames;
24001
+ let matchedToolSets = /* @__PURE__ */ new Set();
23838
24002
  if (clientToolsFilter && clientTools?.length) {
23839
24003
  if (!userMessageEmbeddingsFailed) {
23840
24004
  const clientToolNames = clientToolsFilter(userMessageEmbeddings ?? null, clientTools);
@@ -23851,11 +24015,12 @@ function useChatStorage(options) {
23851
24015
  clientToolEmbeddingsCacheRef.current,
23852
24016
  { getToken, baseUrl, model: embeddingModel },
23853
24017
  extraToolSets,
23854
- activeToolSetsRef.current,
24018
+ mergeActiveToolSets(activeToolSetsRef.current ?? [], carriedToolSets(database, convId)),
23855
24019
  userMessageEmbeddingsFailed ? "error" : "short-prompt"
23856
24020
  );
23857
24021
  filteredClientTools = clientFilterResult.tools;
23858
24022
  clientActivatedSetNames = clientFilterResult.activatedSetNames;
24023
+ matchedToolSets = clientFilterResult.matchedSetNames;
23859
24024
  }
23860
24025
  if (!userMsgQueueId) {
23861
24026
  if (userMessageEmbeddings && autoEmbedMessages) {
@@ -23980,6 +24145,7 @@ function useChatStorage(options) {
23980
24145
  ],
23981
24146
  usage: void 0
23982
24147
  };
24148
+ recordToolSetTurn(database, convId, matchedToolSets);
23983
24149
  return {
23984
24150
  data: responseData2,
23985
24151
  error: null,
@@ -24017,6 +24183,7 @@ function useChatStorage(options) {
24017
24183
  userMessage: { ...storedUserMessage, error: errorMessage }
24018
24184
  };
24019
24185
  }
24186
+ recordToolSetTurn(database, convId, matchedToolSets);
24020
24187
  const responseData = result.data;
24021
24188
  let assistantContent = "";
24022
24189
  let thinkingContent;
@@ -29403,78 +29570,158 @@ import {
29403
29570
  useState as useState16
29404
29571
  } from "react";
29405
29572
 
29573
+ // src/lib/auth/tokenRows.ts
29574
+ var ENCRYPTED_PREFIX = "enc:oauth:";
29575
+ function parsePlaintextToken(raw, walletAddress) {
29576
+ let parsed;
29577
+ try {
29578
+ parsed = JSON.parse(raw);
29579
+ } catch {
29580
+ return null;
29581
+ }
29582
+ if (!parsed || typeof parsed !== "object") return null;
29583
+ const record = parsed;
29584
+ const data = record.token?.accessToken ? record.token : record;
29585
+ if (!data?.accessToken) return null;
29586
+ if (record.wallet && record.wallet !== walletAddress) return null;
29587
+ return data;
29588
+ }
29589
+ function promoteUnscopedRow(raw, data, store, scopedKey, unscopedKey, walletAddress) {
29590
+ const row = raw.startsWith(ENCRYPTED_PREFIX) ? raw : JSON.stringify({ wallet: walletAddress, token: data });
29591
+ if (!store.getItem(scopedKey)) {
29592
+ store.setItem(scopedKey, row);
29593
+ }
29594
+ store.removeItem(unscopedKey);
29595
+ }
29596
+ function readPlaintextToken(scopedKey, unscopedKey, walletAddress) {
29597
+ if (typeof window === "undefined") return null;
29598
+ const keys = scopedKey === unscopedKey ? [scopedKey] : [scopedKey, unscopedKey];
29599
+ for (const key of keys) {
29600
+ const candidates = [
29601
+ [localStorage.getItem(key), localStorage],
29602
+ [sessionStorage.getItem(key), sessionStorage]
29603
+ ];
29604
+ for (const [raw, store] of candidates) {
29605
+ if (!raw) continue;
29606
+ const data = parsePlaintextToken(raw, walletAddress);
29607
+ if (!data) continue;
29608
+ if (walletAddress && key === unscopedKey) {
29609
+ promoteUnscopedRow(raw, data, store, scopedKey, unscopedKey, walletAddress);
29610
+ }
29611
+ return data;
29612
+ }
29613
+ }
29614
+ return null;
29615
+ }
29616
+
29406
29617
  // src/lib/backup/oauth/storage.ts
29407
29618
  var STORAGE_KEY_PREFIX = "oauth_token_";
29408
- var ENCRYPTED_PREFIX = "enc:oauth:";
29409
- function getStorageKey(provider) {
29410
- return `${STORAGE_KEY_PREFIX}${provider}`;
29619
+ var ENCRYPTED_PREFIX2 = "enc:oauth:";
29620
+ function getStorageKey(provider, walletAddress) {
29621
+ const base = `${STORAGE_KEY_PREFIX}${provider}`;
29622
+ return walletAddress ? `${base}:${walletAddress}` : base;
29623
+ }
29624
+ function readRawRows(keys) {
29625
+ const rows = [];
29626
+ for (const key of keys) {
29627
+ for (const store of [localStorage, sessionStorage]) {
29628
+ const raw = store.getItem(key);
29629
+ if (raw) rows.push({ raw, key, store });
29630
+ }
29631
+ }
29632
+ return rows;
29411
29633
  }
29412
29634
  async function getStoredTokenData(provider, walletAddress) {
29413
29635
  if (typeof window === "undefined") return null;
29414
29636
  try {
29415
- const key = getStorageKey(provider);
29416
- let stored = localStorage.getItem(key);
29417
- if (!stored) {
29418
- stored = sessionStorage.getItem(key);
29419
- }
29420
- if (!stored) return null;
29421
- if (stored.startsWith(ENCRYPTED_PREFIX)) {
29422
- if (!walletAddress) {
29423
- getLogger().warn(
29424
- `Encrypted OAuth token found for ${provider} but no wallet address provided`
29425
- );
29426
- return null;
29427
- }
29428
- try {
29429
- const encryptedData = stored.slice(ENCRYPTED_PREFIX.length);
29430
- let decryptedJson;
29431
- try {
29432
- decryptedJson = await decryptData(encryptedData, walletAddress);
29433
- } catch {
29434
- decryptedJson = await decryptData(encryptedData, walletAddress, "v2");
29435
- }
29436
- const data2 = JSON.parse(decryptedJson);
29437
- if (!data2.accessToken) return null;
29438
- return data2;
29439
- } catch (error) {
29440
- getLogger().error(`Failed to decrypt OAuth token for ${provider}:`, error);
29441
- return null;
29637
+ const scopedKey = getStorageKey(provider, walletAddress);
29638
+ const legacyKey = getStorageKey(provider);
29639
+ const keys = scopedKey === legacyKey ? [legacyKey] : [scopedKey, legacyKey];
29640
+ for (const row of readRawRows(keys)) {
29641
+ const data = await readTokenRow(row.raw, provider, walletAddress);
29642
+ if (!data) continue;
29643
+ if (walletAddress && row.key === legacyKey) {
29644
+ promoteUnscopedRow(row.raw, data, row.store, scopedKey, legacyKey, walletAddress);
29442
29645
  }
29646
+ return data;
29443
29647
  }
29444
- const data = JSON.parse(stored);
29445
- if (!data.accessToken) return null;
29446
- return data;
29648
+ return null;
29447
29649
  } catch {
29448
29650
  return null;
29449
29651
  }
29450
29652
  }
29653
+ async function readTokenRow(stored, provider, walletAddress) {
29654
+ if (stored.startsWith(ENCRYPTED_PREFIX2)) {
29655
+ if (!walletAddress) {
29656
+ getLogger().warn(
29657
+ `Encrypted OAuth token found for ${provider} but no wallet address provided`
29658
+ );
29659
+ return null;
29660
+ }
29661
+ try {
29662
+ const encryptedData = stored.slice(ENCRYPTED_PREFIX2.length);
29663
+ let decryptedJson;
29664
+ try {
29665
+ decryptedJson = await decryptData(encryptedData, walletAddress);
29666
+ } catch {
29667
+ decryptedJson = await decryptData(encryptedData, walletAddress, "v2");
29668
+ }
29669
+ const data = JSON.parse(decryptedJson);
29670
+ if (!data.accessToken) return null;
29671
+ return data;
29672
+ } catch (error) {
29673
+ getLogger().error(`Failed to decrypt OAuth token for ${provider}:`, error);
29674
+ return null;
29675
+ }
29676
+ }
29677
+ return parsePlaintextToken(stored, walletAddress);
29678
+ }
29451
29679
  async function storeTokenData(provider, data, walletAddress) {
29452
29680
  if (typeof window === "undefined") return;
29453
- const key = getStorageKey(provider);
29681
+ const key = getStorageKey(provider, walletAddress);
29454
29682
  const json4 = JSON.stringify(data);
29683
+ const plaintextRecord = JSON.stringify({
29684
+ wallet: walletAddress,
29685
+ token: data
29686
+ });
29455
29687
  if (walletAddress) {
29456
29688
  try {
29457
29689
  const encrypted = await encryptData(json4, walletAddress);
29458
- localStorage.setItem(key, `${ENCRYPTED_PREFIX}${encrypted}`);
29690
+ localStorage.setItem(key, `${ENCRYPTED_PREFIX2}${encrypted}`);
29691
+ sessionStorage.removeItem(key);
29459
29692
  } catch (error) {
29460
29693
  getLogger().warn(
29461
29694
  `Failed to encrypt OAuth token for ${provider}, storing temporarily:`,
29462
29695
  error
29463
29696
  );
29464
- sessionStorage.setItem(key, json4);
29697
+ sessionStorage.setItem(key, plaintextRecord);
29465
29698
  throw new Error(
29466
29699
  `OAuth token encryption failed: ${error instanceof Error ? error.message : String(error)}`
29467
29700
  );
29468
29701
  }
29469
29702
  } else {
29470
- sessionStorage.setItem(key, json4);
29703
+ sessionStorage.setItem(key, plaintextRecord);
29471
29704
  }
29472
29705
  }
29473
- function clearTokenData(provider) {
29706
+ function clearTokenData(provider, walletAddress) {
29474
29707
  if (typeof window === "undefined") return;
29475
- const key = getStorageKey(provider);
29476
- localStorage.removeItem(key);
29477
- sessionStorage.removeItem(key);
29708
+ const base = getStorageKey(provider);
29709
+ const keys = walletAddress ? [getStorageKey(provider, walletAddress), base] : [base];
29710
+ if (!walletAddress) keys.push(...suffixedKeys(base));
29711
+ for (const key of keys) {
29712
+ localStorage.removeItem(key);
29713
+ sessionStorage.removeItem(key);
29714
+ }
29715
+ }
29716
+ function suffixedKeys(base) {
29717
+ const found = [];
29718
+ for (const storage of [localStorage, sessionStorage]) {
29719
+ for (let i = 0; i < storage.length; i++) {
29720
+ const key = storage.key(i);
29721
+ if (key && key.startsWith(`${base}:`) && !found.includes(key)) found.push(key);
29722
+ }
29723
+ }
29724
+ return found;
29478
29725
  }
29479
29726
  function isTokenExpired(data, bufferSeconds = 60) {
29480
29727
  if (!data) return true;
@@ -29498,22 +29745,40 @@ async function getRefreshToken(provider, walletAddress) {
29498
29745
  async function migrateUnencryptedTokens(provider, walletAddress) {
29499
29746
  if (typeof window === "undefined") return false;
29500
29747
  try {
29501
- const key = getStorageKey(provider);
29502
- const localStored = localStorage.getItem(key);
29503
- const sessionStored = sessionStorage.getItem(key);
29504
- const isEncrypted2 = (value) => !!value && value.startsWith(ENCRYPTED_PREFIX);
29505
- const tokenToMigrate = sessionStored && !isEncrypted2(sessionStored) ? sessionStored : localStored && !isEncrypted2(localStored) ? localStored : null;
29748
+ const scopedKey = getStorageKey(provider, walletAddress);
29749
+ const legacyKey = getStorageKey(provider);
29750
+ const keys = [scopedKey, legacyKey];
29751
+ const isEncrypted2 = (value) => !!value && value.startsWith(ENCRYPTED_PREFIX2);
29752
+ const plaintextAt = (key) => {
29753
+ const stored = sessionStorage.getItem(key) ?? localStorage.getItem(key);
29754
+ return stored && !isEncrypted2(stored) ? stored : null;
29755
+ };
29756
+ let tokenToMigrate = null;
29757
+ for (const key of keys) {
29758
+ const value = plaintextAt(key);
29759
+ if (value) {
29760
+ tokenToMigrate = value;
29761
+ break;
29762
+ }
29763
+ }
29506
29764
  if (!tokenToMigrate) {
29507
- if (isEncrypted2(localStored) && sessionStored && !isEncrypted2(sessionStored)) {
29508
- sessionStorage.removeItem(key);
29765
+ for (const key of keys) {
29766
+ const stored = sessionStorage.getItem(key);
29767
+ if (isEncrypted2(localStorage.getItem(key)) && stored && !isEncrypted2(stored)) {
29768
+ sessionStorage.removeItem(key);
29769
+ }
29509
29770
  }
29510
29771
  return false;
29511
29772
  }
29512
29773
  try {
29513
- const data = JSON.parse(tokenToMigrate);
29774
+ const data = parsePlaintextToken(tokenToMigrate, walletAddress);
29775
+ if (!data) return false;
29514
29776
  await storeTokenData(provider, data, walletAddress);
29515
- if (sessionStored && !isEncrypted2(sessionStored)) {
29516
- sessionStorage.removeItem(key);
29777
+ for (const key of keys) {
29778
+ if (plaintextAt(key)) sessionStorage.removeItem(key);
29779
+ if (key === legacyKey && !isEncrypted2(localStorage.getItem(key))) {
29780
+ localStorage.removeItem(key);
29781
+ }
29517
29782
  }
29518
29783
  return true;
29519
29784
  } catch (error) {
@@ -29682,7 +29947,7 @@ async function refreshDropboxToken(apiClient, walletAddress) {
29682
29947
  await storeTokenData(PROVIDER, tokenData, walletAddress);
29683
29948
  return response.data.access_token;
29684
29949
  } catch {
29685
- clearTokenData(PROVIDER);
29950
+ clearTokenData(PROVIDER, walletAddress);
29686
29951
  return null;
29687
29952
  }
29688
29953
  }
@@ -29698,7 +29963,7 @@ async function revokeDropboxToken(apiClient, walletAddress) {
29698
29963
  });
29699
29964
  } catch {
29700
29965
  } finally {
29701
- clearTokenData(PROVIDER);
29966
+ clearTokenData(PROVIDER, walletAddress);
29702
29967
  }
29703
29968
  }
29704
29969
  async function getDropboxAccessToken(apiClient, walletAddress) {
@@ -30307,7 +30572,7 @@ async function refreshGoogleDriveToken(apiClient, walletAddress) {
30307
30572
  await storeTokenData(PROVIDER2, tokenData, walletAddress);
30308
30573
  return response.data.access_token;
30309
30574
  } catch {
30310
- clearTokenData(PROVIDER2);
30575
+ clearTokenData(PROVIDER2, walletAddress);
30311
30576
  return null;
30312
30577
  }
30313
30578
  }
@@ -30323,7 +30588,7 @@ async function revokeGoogleDriveToken(apiClient, walletAddress) {
30323
30588
  });
30324
30589
  } catch {
30325
30590
  } finally {
30326
- clearTokenData(PROVIDER2);
30591
+ clearTokenData(PROVIDER2, walletAddress);
30327
30592
  }
30328
30593
  }
30329
30594
  async function getGoogleDriveAccessToken(apiClient, walletAddress) {
@@ -31966,7 +32231,7 @@ var CODE_STORAGE_KEY2 = "google_calendar_oauth_state";
31966
32231
  var TOKEN_STORAGE_KEY = "oauth_token_google-calendar";
31967
32232
  var RETURN_URL_KEY = "google_calendar_return_url";
31968
32233
  var PENDING_MESSAGE_KEY = "google_calendar_pending_message";
31969
- var ENCRYPTED_PREFIX2 = "enc:oauth:";
32234
+ var ENCRYPTED_PREFIX3 = "enc:oauth:";
31970
32235
  var cachedAccessToken = null;
31971
32236
  var cachedExpiresAt = null;
31972
32237
  var cachedRefreshToken = null;
@@ -31997,9 +32262,9 @@ async function getStoredTokenData2(walletAddress) {
31997
32262
  }
31998
32263
  try {
31999
32264
  const scopedStored = localStorage.getItem(getTokenStorageKey(walletAddress));
32000
- if (scopedStored && scopedStored.startsWith(ENCRYPTED_PREFIX2) && walletAddress && hasEncryptionKey(walletAddress)) {
32265
+ if (scopedStored && scopedStored.startsWith(ENCRYPTED_PREFIX3) && walletAddress && hasEncryptionKey(walletAddress)) {
32001
32266
  try {
32002
- const encryptedData = scopedStored.slice(ENCRYPTED_PREFIX2.length);
32267
+ const encryptedData = scopedStored.slice(ENCRYPTED_PREFIX3.length);
32003
32268
  const cryptoKey = await getEncryptionKey(walletAddress);
32004
32269
  const decryptedJson = await decryptDataWithKey(encryptedData, cryptoKey);
32005
32270
  const data = JSON.parse(decryptedJson);
@@ -32014,33 +32279,18 @@ async function getStoredTokenData2(walletAddress) {
32014
32279
  getLogger().error("Failed to decrypt Calendar OAuth token:", error);
32015
32280
  }
32016
32281
  }
32017
- const legacyStored = localStorage.getItem(TOKEN_STORAGE_KEY);
32018
- if (legacyStored && !legacyStored.startsWith(ENCRYPTED_PREFIX2)) {
32019
- try {
32020
- const data = JSON.parse(legacyStored);
32021
- if (data.accessToken) {
32022
- cachedAccessToken = data.accessToken;
32023
- cachedExpiresAt = data.expiresAt ?? null;
32024
- cachedRefreshToken = data.refreshToken ?? null;
32025
- cachedWalletAddress = walletAddress ?? null;
32026
- return data;
32027
- }
32028
- } catch {
32029
- }
32030
- }
32031
- const sessionStored = sessionStorage.getItem(TOKEN_STORAGE_KEY);
32032
- if (sessionStored) {
32033
- try {
32034
- const data = JSON.parse(sessionStored);
32035
- if (!data.accessToken) return null;
32036
- cachedAccessToken = data.accessToken;
32037
- cachedExpiresAt = data.expiresAt ?? null;
32038
- cachedRefreshToken = data.refreshToken ?? null;
32039
- cachedScope = data.scope ?? null;
32040
- cachedWalletAddress = walletAddress ?? null;
32041
- return data;
32042
- } catch {
32043
- }
32282
+ const plaintext = readPlaintextToken(
32283
+ getTokenStorageKey(walletAddress),
32284
+ TOKEN_STORAGE_KEY,
32285
+ walletAddress
32286
+ );
32287
+ if (plaintext) {
32288
+ cachedAccessToken = plaintext.accessToken;
32289
+ cachedExpiresAt = plaintext.expiresAt ?? null;
32290
+ cachedRefreshToken = plaintext.refreshToken ?? null;
32291
+ cachedScope = plaintext.scope ?? null;
32292
+ cachedWalletAddress = walletAddress ?? null;
32293
+ return plaintext;
32044
32294
  }
32045
32295
  return null;
32046
32296
  } catch {
@@ -32055,16 +32305,19 @@ async function storeTokenData2(data, walletAddress) {
32055
32305
  cachedScope = data.scope ?? null;
32056
32306
  cachedWalletAddress = walletAddress ?? null;
32057
32307
  const json4 = JSON.stringify(data);
32058
- sessionStorage.setItem(TOKEN_STORAGE_KEY, json4);
32059
32308
  if (walletAddress && hasEncryptionKey(walletAddress)) {
32060
32309
  try {
32061
32310
  const cryptoKey = await getEncryptionKey(walletAddress);
32062
32311
  const encrypted = await encryptDataWithKey(json4, cryptoKey);
32063
- localStorage.setItem(getTokenStorageKey(walletAddress), ENCRYPTED_PREFIX2 + encrypted);
32312
+ localStorage.setItem(getTokenStorageKey(walletAddress), ENCRYPTED_PREFIX3 + encrypted);
32313
+ sessionStorage.removeItem(getTokenStorageKey(walletAddress));
32314
+ return;
32064
32315
  } catch (error) {
32065
32316
  getLogger().warn("Failed to encrypt Calendar OAuth token:", error);
32066
32317
  }
32067
32318
  }
32319
+ const record = { wallet: walletAddress, token: data };
32320
+ sessionStorage.setItem(getTokenStorageKey(walletAddress), JSON.stringify(record));
32068
32321
  }
32069
32322
  function clearCalendarToken(walletAddress) {
32070
32323
  if (typeof window === "undefined") return;
@@ -32078,6 +32331,7 @@ function clearCalendarToken(walletAddress) {
32078
32331
  localStorage.removeItem(TOKEN_STORAGE_KEY);
32079
32332
  }
32080
32333
  sessionStorage.removeItem(TOKEN_STORAGE_KEY);
32334
+ sessionStorage.removeItem(getTokenStorageKey(walletAddress));
32081
32335
  }
32082
32336
  function isTokenExpired2(data, bufferSeconds = 60) {
32083
32337
  if (!data) return true;
@@ -32259,24 +32513,38 @@ async function migrateCalendarToken(walletAddress) {
32259
32513
  if (typeof window === "undefined") return false;
32260
32514
  if (!walletAddress || !hasEncryptionKey(walletAddress)) return false;
32261
32515
  try {
32262
- const sessionStored = sessionStorage.getItem(TOKEN_STORAGE_KEY);
32263
- const legacyStored = localStorage.getItem(TOKEN_STORAGE_KEY);
32264
- const isLegacyUnencrypted = legacyStored && !legacyStored.startsWith(ENCRYPTED_PREFIX2);
32265
- const unencryptedJson = sessionStored || (isLegacyUnencrypted ? legacyStored : null);
32266
- if (!unencryptedJson) return false;
32267
32516
  const scopedKey = getTokenStorageKey(walletAddress);
32517
+ const sources = [
32518
+ { key: scopedKey, store: sessionStorage },
32519
+ // A read moves a legacy localStorage row here as plain text.
32520
+ { key: scopedKey, store: localStorage },
32521
+ { key: TOKEN_STORAGE_KEY, store: sessionStorage },
32522
+ { key: TOKEN_STORAGE_KEY, store: localStorage }
32523
+ ];
32524
+ let used = null;
32525
+ let unencryptedJson = "";
32526
+ for (const source of sources) {
32527
+ const value = source.store.getItem(source.key);
32528
+ if (value && !value.startsWith(ENCRYPTED_PREFIX3)) {
32529
+ unencryptedJson = value;
32530
+ used = source;
32531
+ break;
32532
+ }
32533
+ }
32534
+ if (!used) return false;
32268
32535
  const existingEncrypted = localStorage.getItem(scopedKey);
32269
- if (existingEncrypted?.startsWith(ENCRYPTED_PREFIX2)) {
32270
- sessionStorage.removeItem(TOKEN_STORAGE_KEY);
32271
- if (isLegacyUnencrypted) localStorage.removeItem(TOKEN_STORAGE_KEY);
32536
+ if (existingEncrypted?.startsWith(ENCRYPTED_PREFIX3)) {
32537
+ used.store.removeItem(used.key);
32272
32538
  return true;
32273
32539
  }
32274
- const data = JSON.parse(unencryptedJson);
32540
+ const data = parsePlaintextToken(unencryptedJson, walletAddress);
32541
+ if (!data) return false;
32275
32542
  await storeTokenData2(data, walletAddress);
32276
32543
  const migrated = localStorage.getItem(scopedKey);
32277
- if (!migrated?.startsWith(ENCRYPTED_PREFIX2)) return false;
32278
- sessionStorage.removeItem(TOKEN_STORAGE_KEY);
32279
- if (isLegacyUnencrypted) localStorage.removeItem(TOKEN_STORAGE_KEY);
32544
+ if (!migrated?.startsWith(ENCRYPTED_PREFIX3)) return false;
32545
+ if (used.store !== localStorage || used.key !== scopedKey) {
32546
+ used.store.removeItem(used.key);
32547
+ }
32280
32548
  return true;
32281
32549
  } catch {
32282
32550
  return false;
@@ -32289,7 +32557,7 @@ var CODE_STORAGE_KEY3 = "google_drive_oauth_state";
32289
32557
  var TOKEN_STORAGE_KEY2 = "oauth_token_google-drive-full";
32290
32558
  var RETURN_URL_KEY2 = "google_drive_return_url";
32291
32559
  var PENDING_MESSAGE_KEY2 = "google_drive_pending_message";
32292
- var ENCRYPTED_PREFIX3 = "enc:oauth:";
32560
+ var ENCRYPTED_PREFIX4 = "enc:oauth:";
32293
32561
  var cachedAccessToken2 = null;
32294
32562
  var cachedExpiresAt2 = null;
32295
32563
  var cachedRefreshToken2 = null;
@@ -32320,9 +32588,9 @@ async function getStoredTokenData3(walletAddress) {
32320
32588
  }
32321
32589
  try {
32322
32590
  const scopedStored = localStorage.getItem(getTokenStorageKey2(walletAddress));
32323
- if (scopedStored && scopedStored.startsWith(ENCRYPTED_PREFIX3) && walletAddress && hasEncryptionKey(walletAddress)) {
32591
+ if (scopedStored && scopedStored.startsWith(ENCRYPTED_PREFIX4) && walletAddress && hasEncryptionKey(walletAddress)) {
32324
32592
  try {
32325
- const encryptedData = scopedStored.slice(ENCRYPTED_PREFIX3.length);
32593
+ const encryptedData = scopedStored.slice(ENCRYPTED_PREFIX4.length);
32326
32594
  const cryptoKey = await getEncryptionKey(walletAddress);
32327
32595
  const decryptedJson = await decryptDataWithKey(encryptedData, cryptoKey);
32328
32596
  const data = JSON.parse(decryptedJson);
@@ -32337,33 +32605,18 @@ async function getStoredTokenData3(walletAddress) {
32337
32605
  getLogger().error("Failed to decrypt Drive OAuth token:", error);
32338
32606
  }
32339
32607
  }
32340
- const legacyStored = localStorage.getItem(TOKEN_STORAGE_KEY2);
32341
- if (legacyStored && !legacyStored.startsWith(ENCRYPTED_PREFIX3)) {
32342
- try {
32343
- const data = JSON.parse(legacyStored);
32344
- if (data.accessToken) {
32345
- cachedAccessToken2 = data.accessToken;
32346
- cachedExpiresAt2 = data.expiresAt ?? null;
32347
- cachedRefreshToken2 = data.refreshToken ?? null;
32348
- cachedWalletAddress2 = walletAddress ?? null;
32349
- return data;
32350
- }
32351
- } catch {
32352
- }
32353
- }
32354
- const sessionStored = sessionStorage.getItem(TOKEN_STORAGE_KEY2);
32355
- if (sessionStored) {
32356
- try {
32357
- const data = JSON.parse(sessionStored);
32358
- if (!data.accessToken) return null;
32359
- cachedAccessToken2 = data.accessToken;
32360
- cachedExpiresAt2 = data.expiresAt ?? null;
32361
- cachedRefreshToken2 = data.refreshToken ?? null;
32362
- cachedScope2 = data.scope ?? null;
32363
- cachedWalletAddress2 = walletAddress ?? null;
32364
- return data;
32365
- } catch {
32366
- }
32608
+ const plaintext = readPlaintextToken(
32609
+ getTokenStorageKey2(walletAddress),
32610
+ TOKEN_STORAGE_KEY2,
32611
+ walletAddress
32612
+ );
32613
+ if (plaintext) {
32614
+ cachedAccessToken2 = plaintext.accessToken;
32615
+ cachedExpiresAt2 = plaintext.expiresAt ?? null;
32616
+ cachedRefreshToken2 = plaintext.refreshToken ?? null;
32617
+ cachedScope2 = plaintext.scope ?? null;
32618
+ cachedWalletAddress2 = walletAddress ?? null;
32619
+ return plaintext;
32367
32620
  }
32368
32621
  return null;
32369
32622
  } catch {
@@ -32378,16 +32631,19 @@ async function storeTokenData3(data, walletAddress) {
32378
32631
  cachedScope2 = data.scope ?? null;
32379
32632
  cachedWalletAddress2 = walletAddress ?? null;
32380
32633
  const json4 = JSON.stringify(data);
32381
- sessionStorage.setItem(TOKEN_STORAGE_KEY2, json4);
32382
32634
  if (walletAddress && hasEncryptionKey(walletAddress)) {
32383
32635
  try {
32384
32636
  const cryptoKey = await getEncryptionKey(walletAddress);
32385
32637
  const encrypted = await encryptDataWithKey(json4, cryptoKey);
32386
- localStorage.setItem(getTokenStorageKey2(walletAddress), `${ENCRYPTED_PREFIX3}${encrypted}`);
32638
+ localStorage.setItem(getTokenStorageKey2(walletAddress), `${ENCRYPTED_PREFIX4}${encrypted}`);
32639
+ sessionStorage.removeItem(getTokenStorageKey2(walletAddress));
32640
+ return;
32387
32641
  } catch (error) {
32388
32642
  getLogger().warn("Failed to encrypt Drive OAuth token:", error);
32389
32643
  }
32390
32644
  }
32645
+ const record = { wallet: walletAddress, token: data };
32646
+ sessionStorage.setItem(getTokenStorageKey2(walletAddress), JSON.stringify(record));
32391
32647
  }
32392
32648
  function clearDriveToken(walletAddress) {
32393
32649
  if (typeof window === "undefined") return;
@@ -32401,6 +32657,7 @@ function clearDriveToken(walletAddress) {
32401
32657
  localStorage.removeItem(TOKEN_STORAGE_KEY2);
32402
32658
  }
32403
32659
  sessionStorage.removeItem(TOKEN_STORAGE_KEY2);
32660
+ sessionStorage.removeItem(getTokenStorageKey2(walletAddress));
32404
32661
  }
32405
32662
  function isTokenExpired3(data, bufferSeconds = 60) {
32406
32663
  if (!data) return true;
@@ -32582,24 +32839,38 @@ async function migrateDriveToken(walletAddress) {
32582
32839
  if (typeof window === "undefined") return false;
32583
32840
  if (!walletAddress || !hasEncryptionKey(walletAddress)) return false;
32584
32841
  try {
32585
- const sessionStored = sessionStorage.getItem(TOKEN_STORAGE_KEY2);
32586
- const legacyStored = localStorage.getItem(TOKEN_STORAGE_KEY2);
32587
- const isLegacyUnencrypted = legacyStored && !legacyStored.startsWith(ENCRYPTED_PREFIX3);
32588
- const unencryptedJson = sessionStored || (isLegacyUnencrypted ? legacyStored : null);
32589
- if (!unencryptedJson) return false;
32590
32842
  const scopedKey = getTokenStorageKey2(walletAddress);
32843
+ const sources = [
32844
+ { key: scopedKey, store: sessionStorage },
32845
+ // A read moves a legacy localStorage row here as plain text.
32846
+ { key: scopedKey, store: localStorage },
32847
+ { key: TOKEN_STORAGE_KEY2, store: sessionStorage },
32848
+ { key: TOKEN_STORAGE_KEY2, store: localStorage }
32849
+ ];
32850
+ let used = null;
32851
+ let unencryptedJson = "";
32852
+ for (const source of sources) {
32853
+ const value = source.store.getItem(source.key);
32854
+ if (value && !value.startsWith(ENCRYPTED_PREFIX4)) {
32855
+ unencryptedJson = value;
32856
+ used = source;
32857
+ break;
32858
+ }
32859
+ }
32860
+ if (!used) return false;
32591
32861
  const existingEncrypted = localStorage.getItem(scopedKey);
32592
- if (existingEncrypted?.startsWith(ENCRYPTED_PREFIX3)) {
32593
- sessionStorage.removeItem(TOKEN_STORAGE_KEY2);
32594
- if (isLegacyUnencrypted) localStorage.removeItem(TOKEN_STORAGE_KEY2);
32862
+ if (existingEncrypted?.startsWith(ENCRYPTED_PREFIX4)) {
32863
+ used.store.removeItem(used.key);
32595
32864
  return true;
32596
32865
  }
32597
- const data = JSON.parse(unencryptedJson);
32866
+ const data = parsePlaintextToken(unencryptedJson, walletAddress);
32867
+ if (!data) return false;
32598
32868
  await storeTokenData3(data, walletAddress);
32599
32869
  const migrated = localStorage.getItem(scopedKey);
32600
- if (!migrated?.startsWith(ENCRYPTED_PREFIX3)) return false;
32601
- sessionStorage.removeItem(TOKEN_STORAGE_KEY2);
32602
- if (isLegacyUnencrypted) localStorage.removeItem(TOKEN_STORAGE_KEY2);
32870
+ if (!migrated?.startsWith(ENCRYPTED_PREFIX4)) return false;
32871
+ if (used.store !== localStorage || used.key !== scopedKey) {
32872
+ used.store.removeItem(used.key);
32873
+ }
32603
32874
  return true;
32604
32875
  } catch {
32605
32876
  return false;
@@ -32631,7 +32902,7 @@ var FALLBACK_OAUTH_AUTHORIZE = "https://api.notion.com/v1/oauth/authorize";
32631
32902
  var FALLBACK_OAUTH_TOKEN = "https://api.notion.com/v1/oauth/token";
32632
32903
  var FALLBACK_REGISTRATION = "https://api.notion.com/v1/oauth/register";
32633
32904
  var DEFAULT_TOKEN_EXPIRY_SECONDS = 8 * 3600;
32634
- var ENCRYPTED_PREFIX4 = "enc:oauth:";
32905
+ var ENCRYPTED_PREFIX5 = "enc:oauth:";
32635
32906
  var cachedAccessToken3 = null;
32636
32907
  var cachedExpiresAt3 = null;
32637
32908
  var cachedWalletAddress3 = null;
@@ -32769,12 +33040,14 @@ async function storeTokenData4(data, walletAddress) {
32769
33040
  try {
32770
33041
  const cryptoKey = await getEncryptionKey(walletAddress);
32771
33042
  const encrypted = await encryptDataWithKey(json4, cryptoKey);
32772
- localStorage.setItem(getTokenStorageKey3(walletAddress), `${ENCRYPTED_PREFIX4}${encrypted}`);
33043
+ localStorage.setItem(getTokenStorageKey3(walletAddress), `${ENCRYPTED_PREFIX5}${encrypted}`);
33044
+ sessionStorage.removeItem(getTokenStorageKey3(walletAddress));
32773
33045
  return;
32774
33046
  } catch {
32775
33047
  }
32776
33048
  }
32777
- sessionStorage.setItem(TOKEN_STORAGE_KEY3, json4);
33049
+ const record = { wallet: walletAddress, token: data };
33050
+ sessionStorage.setItem(getTokenStorageKey3(walletAddress), JSON.stringify(record));
32778
33051
  }
32779
33052
  async function getStoredTokenData4(walletAddress) {
32780
33053
  if (typeof window === "undefined") return null;
@@ -32791,11 +33064,11 @@ async function getStoredTokenData4(walletAddress) {
32791
33064
  }
32792
33065
  try {
32793
33066
  const stored = localStorage.getItem(getTokenStorageKey3(walletAddress));
32794
- if (stored?.startsWith(ENCRYPTED_PREFIX4)) {
33067
+ if (stored?.startsWith(ENCRYPTED_PREFIX5)) {
32795
33068
  if (walletAddress && hasEncryptionKey(walletAddress)) {
32796
33069
  try {
32797
33070
  const cryptoKey = await getEncryptionKey(walletAddress);
32798
- const encrypted = stored.slice(ENCRYPTED_PREFIX4.length);
33071
+ const encrypted = stored.slice(ENCRYPTED_PREFIX5.length);
32799
33072
  const decrypted = await decryptDataWithKey(encrypted, cryptoKey);
32800
33073
  const data = JSON.parse(decrypted);
32801
33074
  if (data.accessToken) return data;
@@ -32803,12 +33076,12 @@ async function getStoredTokenData4(walletAddress) {
32803
33076
  }
32804
33077
  }
32805
33078
  }
32806
- const sessionStored = sessionStorage.getItem(TOKEN_STORAGE_KEY3);
32807
- if (sessionStored) {
32808
- const data = JSON.parse(sessionStored);
32809
- if (!data.accessToken) return null;
32810
- return data;
32811
- }
33079
+ const plaintext = readPlaintextToken(
33080
+ getTokenStorageKey3(walletAddress),
33081
+ TOKEN_STORAGE_KEY3,
33082
+ walletAddress
33083
+ );
33084
+ if (plaintext) return plaintext;
32812
33085
  return null;
32813
33086
  } catch {
32814
33087
  return null;
@@ -32818,6 +33091,7 @@ function clearNotionToken(walletAddress) {
32818
33091
  if (typeof window === "undefined") return;
32819
33092
  localStorage.removeItem(getTokenStorageKey3(walletAddress));
32820
33093
  sessionStorage.removeItem(TOKEN_STORAGE_KEY3);
33094
+ sessionStorage.removeItem(getTokenStorageKey3(walletAddress));
32821
33095
  cachedAccessToken3 = null;
32822
33096
  cachedExpiresAt3 = null;
32823
33097
  cachedWalletAddress3 = null;
@@ -32833,20 +33107,34 @@ async function migrateNotionToken(walletAddress) {
32833
33107
  if (typeof window === "undefined") return false;
32834
33108
  if (!walletAddress || !hasEncryptionKey(walletAddress)) return false;
32835
33109
  try {
32836
- const sessionStored = sessionStorage.getItem(TOKEN_STORAGE_KEY3);
32837
- if (!sessionStored) return false;
32838
33110
  const scopedKey = getTokenStorageKey3(walletAddress);
33111
+ const sources = [
33112
+ { key: scopedKey, store: sessionStorage },
33113
+ { key: TOKEN_STORAGE_KEY3, store: sessionStorage }
33114
+ ];
33115
+ let used = null;
33116
+ let unencryptedJson = "";
33117
+ for (const source of sources) {
33118
+ const value = source.store.getItem(source.key);
33119
+ if (value && !value.startsWith(ENCRYPTED_PREFIX5)) {
33120
+ unencryptedJson = value;
33121
+ used = source;
33122
+ break;
33123
+ }
33124
+ }
33125
+ if (!used) return false;
32839
33126
  const localStored = localStorage.getItem(scopedKey);
32840
- if (localStored?.startsWith(ENCRYPTED_PREFIX4)) {
33127
+ if (localStored?.startsWith(ENCRYPTED_PREFIX5)) {
32841
33128
  localStorage.removeItem(scopedKey);
32842
33129
  }
32843
- const data = JSON.parse(sessionStored);
33130
+ const data = parsePlaintextToken(unencryptedJson, walletAddress);
33131
+ if (!data) return false;
32844
33132
  await storeTokenData4(data, walletAddress);
32845
33133
  const migrated = localStorage.getItem(scopedKey);
32846
- if (!migrated?.startsWith(ENCRYPTED_PREFIX4)) {
33134
+ if (!migrated?.startsWith(ENCRYPTED_PREFIX5)) {
32847
33135
  return false;
32848
33136
  }
32849
- sessionStorage.removeItem(TOKEN_STORAGE_KEY3);
33137
+ used.store.removeItem(used.key);
32850
33138
  return true;
32851
33139
  } catch {
32852
33140
  return false;
@@ -32858,12 +33146,12 @@ async function migrateNotionClientRegistration(walletAddress) {
32858
33146
  try {
32859
33147
  const sessionStored = sessionStorage.getItem(CLIENT_REGISTRATION_KEY);
32860
33148
  const legacyStored = localStorage.getItem(CLIENT_REGISTRATION_KEY);
32861
- const isLegacyUnencrypted = legacyStored && !legacyStored.startsWith(ENCRYPTED_PREFIX4);
33149
+ const isLegacyUnencrypted = legacyStored && !legacyStored.startsWith(ENCRYPTED_PREFIX5);
32862
33150
  const unencryptedJson = sessionStored || (isLegacyUnencrypted ? legacyStored : null);
32863
33151
  if (!unencryptedJson) return false;
32864
33152
  const scopedKey = getClientRegistrationStorageKey(walletAddress);
32865
33153
  const existingEncrypted = localStorage.getItem(scopedKey);
32866
- if (existingEncrypted?.startsWith(ENCRYPTED_PREFIX4)) {
33154
+ if (existingEncrypted?.startsWith(ENCRYPTED_PREFIX5)) {
32867
33155
  sessionStorage.removeItem(CLIENT_REGISTRATION_KEY);
32868
33156
  if (isLegacyUnencrypted) {
32869
33157
  localStorage.removeItem(CLIENT_REGISTRATION_KEY);
@@ -32873,7 +33161,7 @@ async function migrateNotionClientRegistration(walletAddress) {
32873
33161
  const data = JSON.parse(unencryptedJson);
32874
33162
  await storeClientRegistration(data, walletAddress);
32875
33163
  const migrated = localStorage.getItem(scopedKey);
32876
- if (!migrated?.startsWith(ENCRYPTED_PREFIX4)) {
33164
+ if (!migrated?.startsWith(ENCRYPTED_PREFIX5)) {
32877
33165
  return false;
32878
33166
  }
32879
33167
  sessionStorage.removeItem(CLIENT_REGISTRATION_KEY);
@@ -32890,11 +33178,11 @@ async function getClientRegistration(walletAddress) {
32890
33178
  try {
32891
33179
  const scopedKey = getClientRegistrationStorageKey(walletAddress);
32892
33180
  const stored = localStorage.getItem(scopedKey);
32893
- if (stored?.startsWith(ENCRYPTED_PREFIX4)) {
33181
+ if (stored?.startsWith(ENCRYPTED_PREFIX5)) {
32894
33182
  if (walletAddress && hasEncryptionKey(walletAddress)) {
32895
33183
  try {
32896
33184
  const cryptoKey = await getEncryptionKey(walletAddress);
32897
- const encrypted = stored.slice(ENCRYPTED_PREFIX4.length);
33185
+ const encrypted = stored.slice(ENCRYPTED_PREFIX5.length);
32898
33186
  const decrypted = await decryptDataWithKey(encrypted, cryptoKey);
32899
33187
  const data = JSON.parse(decrypted);
32900
33188
  if (data.clientId) {
@@ -32904,7 +33192,7 @@ async function getClientRegistration(walletAddress) {
32904
33192
  }
32905
33193
  }
32906
33194
  }
32907
- if (stored && !stored.startsWith(ENCRYPTED_PREFIX4)) {
33195
+ if (stored && !stored.startsWith(ENCRYPTED_PREFIX5)) {
32908
33196
  const data = JSON.parse(stored);
32909
33197
  if (!data.clientId) return null;
32910
33198
  return data;
@@ -32929,7 +33217,7 @@ async function storeClientRegistration(registration, walletAddress) {
32929
33217
  const cryptoKey = await getEncryptionKey(walletAddress);
32930
33218
  const encrypted = await encryptDataWithKey(json4, cryptoKey);
32931
33219
  const scopedKey = getClientRegistrationStorageKey(walletAddress);
32932
- localStorage.setItem(scopedKey, `${ENCRYPTED_PREFIX4}${encrypted}`);
33220
+ localStorage.setItem(scopedKey, `${ENCRYPTED_PREFIX5}${encrypted}`);
32933
33221
  } catch {
32934
33222
  }
32935
33223
  }
@@ -33161,7 +33449,7 @@ var CODE_STORAGE_KEY4 = "github_oauth_state";
33161
33449
  var TOKEN_STORAGE_KEY4 = "oauth_token_github";
33162
33450
  var RETURN_URL_KEY4 = "github_return_url";
33163
33451
  var PENDING_MESSAGE_KEY4 = "github_pending_message";
33164
- var ENCRYPTED_PREFIX5 = "enc:oauth:";
33452
+ var ENCRYPTED_PREFIX6 = "enc:oauth:";
33165
33453
  var cachedAccessToken4 = null;
33166
33454
  var cachedExpiresAt4 = null;
33167
33455
  var cachedRefreshToken3 = null;
@@ -33194,9 +33482,9 @@ async function getStoredTokenData5(walletAddress) {
33194
33482
  }
33195
33483
  try {
33196
33484
  const scopedStored = localStorage.getItem(getTokenStorageKey4(walletAddress));
33197
- if (scopedStored && scopedStored.startsWith(ENCRYPTED_PREFIX5) && walletAddress && hasEncryptionKey(walletAddress)) {
33485
+ if (scopedStored && scopedStored.startsWith(ENCRYPTED_PREFIX6) && walletAddress && hasEncryptionKey(walletAddress)) {
33198
33486
  try {
33199
- const encryptedData = scopedStored.slice(ENCRYPTED_PREFIX5.length);
33487
+ const encryptedData = scopedStored.slice(ENCRYPTED_PREFIX6.length);
33200
33488
  const cryptoKey = await getEncryptionKey(walletAddress);
33201
33489
  const decryptedJson = await decryptDataWithKey(encryptedData, cryptoKey);
33202
33490
  const data = JSON.parse(decryptedJson);
@@ -33211,34 +33499,18 @@ async function getStoredTokenData5(walletAddress) {
33211
33499
  getLogger().error("Failed to decrypt GitHub OAuth token:", error);
33212
33500
  }
33213
33501
  }
33214
- const legacyStored = localStorage.getItem(TOKEN_STORAGE_KEY4);
33215
- if (legacyStored && !legacyStored.startsWith(ENCRYPTED_PREFIX5)) {
33216
- try {
33217
- const data = JSON.parse(legacyStored);
33218
- if (data.accessToken) {
33219
- cachedAccessToken4 = data.accessToken;
33220
- cachedExpiresAt4 = data.expiresAt ?? null;
33221
- cachedRefreshToken3 = data.refreshToken ?? null;
33222
- cachedScope3 = data.scope ?? null;
33223
- cachedWalletAddress4 = walletAddress ?? null;
33224
- return data;
33225
- }
33226
- } catch {
33227
- }
33228
- }
33229
- const sessionStored = sessionStorage.getItem(TOKEN_STORAGE_KEY4);
33230
- if (sessionStored) {
33231
- try {
33232
- const data = JSON.parse(sessionStored);
33233
- if (!data.accessToken) return null;
33234
- cachedAccessToken4 = data.accessToken;
33235
- cachedExpiresAt4 = data.expiresAt ?? null;
33236
- cachedRefreshToken3 = data.refreshToken ?? null;
33237
- cachedScope3 = data.scope ?? null;
33238
- cachedWalletAddress4 = walletAddress ?? null;
33239
- return data;
33240
- } catch {
33241
- }
33502
+ const plaintext = readPlaintextToken(
33503
+ getTokenStorageKey4(walletAddress),
33504
+ TOKEN_STORAGE_KEY4,
33505
+ walletAddress
33506
+ );
33507
+ if (plaintext) {
33508
+ cachedAccessToken4 = plaintext.accessToken;
33509
+ cachedExpiresAt4 = plaintext.expiresAt ?? null;
33510
+ cachedRefreshToken3 = plaintext.refreshToken ?? null;
33511
+ cachedScope3 = plaintext.scope ?? null;
33512
+ cachedWalletAddress4 = walletAddress ?? null;
33513
+ return plaintext;
33242
33514
  }
33243
33515
  return null;
33244
33516
  } catch {
@@ -33253,16 +33525,19 @@ async function storeTokenData5(data, walletAddress) {
33253
33525
  cachedScope3 = data.scope ?? null;
33254
33526
  cachedWalletAddress4 = walletAddress ?? null;
33255
33527
  const json4 = JSON.stringify(data);
33256
- sessionStorage.setItem(TOKEN_STORAGE_KEY4, json4);
33257
33528
  if (walletAddress && hasEncryptionKey(walletAddress)) {
33258
33529
  try {
33259
33530
  const cryptoKey = await getEncryptionKey(walletAddress);
33260
33531
  const encrypted = await encryptDataWithKey(json4, cryptoKey);
33261
- localStorage.setItem(getTokenStorageKey4(walletAddress), `${ENCRYPTED_PREFIX5}${encrypted}`);
33532
+ localStorage.setItem(getTokenStorageKey4(walletAddress), `${ENCRYPTED_PREFIX6}${encrypted}`);
33533
+ sessionStorage.removeItem(getTokenStorageKey4(walletAddress));
33534
+ return;
33262
33535
  } catch (error) {
33263
33536
  getLogger().warn("Failed to encrypt GitHub OAuth token:", error);
33264
33537
  }
33265
33538
  }
33539
+ const record = { wallet: walletAddress, token: data };
33540
+ sessionStorage.setItem(getTokenStorageKey4(walletAddress), JSON.stringify(record));
33266
33541
  }
33267
33542
  function clearGithubToken(walletAddress) {
33268
33543
  if (typeof window === "undefined") return;
@@ -33276,6 +33551,7 @@ function clearGithubToken(walletAddress) {
33276
33551
  localStorage.removeItem(TOKEN_STORAGE_KEY4);
33277
33552
  }
33278
33553
  sessionStorage.removeItem(TOKEN_STORAGE_KEY4);
33554
+ sessionStorage.removeItem(getTokenStorageKey4(walletAddress));
33279
33555
  }
33280
33556
  function isTokenExpired5(data, bufferSeconds = 60) {
33281
33557
  if (!data) return true;
@@ -33484,24 +33760,38 @@ async function migrateGithubToken(walletAddress) {
33484
33760
  if (typeof window === "undefined") return false;
33485
33761
  if (!walletAddress || !hasEncryptionKey(walletAddress)) return false;
33486
33762
  try {
33487
- const sessionStored = sessionStorage.getItem(TOKEN_STORAGE_KEY4);
33488
- const legacyStored = localStorage.getItem(TOKEN_STORAGE_KEY4);
33489
- const isLegacyUnencrypted = legacyStored && !legacyStored.startsWith(ENCRYPTED_PREFIX5);
33490
- const unencryptedJson = sessionStored || (isLegacyUnencrypted ? legacyStored : null);
33491
- if (!unencryptedJson) return false;
33492
33763
  const scopedKey = getTokenStorageKey4(walletAddress);
33764
+ const sources = [
33765
+ { key: scopedKey, store: sessionStorage },
33766
+ // A read moves a legacy localStorage row here as plain text.
33767
+ { key: scopedKey, store: localStorage },
33768
+ { key: TOKEN_STORAGE_KEY4, store: sessionStorage },
33769
+ { key: TOKEN_STORAGE_KEY4, store: localStorage }
33770
+ ];
33771
+ let used = null;
33772
+ let unencryptedJson = "";
33773
+ for (const source of sources) {
33774
+ const value = source.store.getItem(source.key);
33775
+ if (value && !value.startsWith(ENCRYPTED_PREFIX6)) {
33776
+ unencryptedJson = value;
33777
+ used = source;
33778
+ break;
33779
+ }
33780
+ }
33781
+ if (!used) return false;
33493
33782
  const existingEncrypted = localStorage.getItem(scopedKey);
33494
- if (existingEncrypted?.startsWith(ENCRYPTED_PREFIX5)) {
33495
- sessionStorage.removeItem(TOKEN_STORAGE_KEY4);
33496
- if (isLegacyUnencrypted) localStorage.removeItem(TOKEN_STORAGE_KEY4);
33783
+ if (existingEncrypted?.startsWith(ENCRYPTED_PREFIX6)) {
33784
+ used.store.removeItem(used.key);
33497
33785
  return true;
33498
33786
  }
33499
- const data = JSON.parse(unencryptedJson);
33787
+ const data = parsePlaintextToken(unencryptedJson, walletAddress);
33788
+ if (!data) return false;
33500
33789
  await storeTokenData5(data, walletAddress);
33501
33790
  const migrated = localStorage.getItem(scopedKey);
33502
- if (!migrated?.startsWith(ENCRYPTED_PREFIX5)) return false;
33503
- sessionStorage.removeItem(TOKEN_STORAGE_KEY4);
33504
- if (isLegacyUnencrypted) localStorage.removeItem(TOKEN_STORAGE_KEY4);
33791
+ if (!migrated?.startsWith(ENCRYPTED_PREFIX6)) return false;
33792
+ if (used.store !== localStorage || used.key !== scopedKey) {
33793
+ used.store.removeItem(used.key);
33794
+ }
33505
33795
  return true;
33506
33796
  } catch {
33507
33797
  return false;