Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Maya Token Extract</title> | |
| <style> | |
| * { box-sizing: border-box; margin: 0; padding: 0; } | |
| body { | |
| background: #0d0d0d; color: #e0e0e0; | |
| font-family: 'Courier New', monospace; | |
| min-height: 100vh; padding: 20px; | |
| } | |
| .container { max-width: 600px; margin: 0 auto; } | |
| h1 { color: #ff6b9d; font-size: 1.1rem; margin-bottom: 16px; letter-spacing: 2px; } | |
| .step { | |
| background: #111; border: 1px solid #222; border-radius: 6px; | |
| padding: 14px; margin-bottom: 12px; | |
| } | |
| .step-num { color: #ff6b9d; font-weight: bold; font-size: 1.1rem; } | |
| .step p { margin-top: 6px; font-size: 0.82rem; line-height: 1.6; color: #bbb; } | |
| .code-box { | |
| background: #0a1510; border: 1px solid #1e4d2a; padding: 10px; | |
| border-radius: 4px; word-break: break-all; font-size: 0.55rem; | |
| color: #4daa72; margin: 8px 0; line-height: 1.4; | |
| user-select: all; cursor: pointer; max-height: 100px; overflow-y: auto; | |
| } | |
| .btn { | |
| background: #ff6b9d; color: #000; border: none; | |
| padding: 12px 20px; font-family: monospace; font-size: 0.85rem; | |
| font-weight: bold; border-radius: 4px; cursor: pointer; | |
| letter-spacing: 1px; width: 100%; margin-top: 8px; | |
| } | |
| .btn:active { opacity: 0.7; } | |
| .btn-alt { background: #1a3d28; color: #4daa72; } | |
| .status { | |
| margin-top: 12px; padding: 10px; border-radius: 4px; | |
| font-size: 0.78rem; display: none; | |
| } | |
| .ok { background: #0a1f13; border: 1px solid #1e5c35; color: #4daa72; display: block; } | |
| .err { background: #1f0a0a; border: 1px solid #5c1e1e; color: #aa4d4d; display: block; } | |
| .info { background: #0a0f1f; border: 1px solid #1e2f5c; color: #4d72aa; display: block; } | |
| .hidden { display: none; } | |
| textarea { | |
| width: 100%; background: #161616; border: 1px solid #2a2a2a; | |
| color: #e0e0e0; padding: 10px; font-family: monospace; | |
| font-size: 0.8rem; border-radius: 4px; resize: vertical; | |
| min-height: 80px; | |
| } | |
| .or-line { text-align: center; color: #333; font-size: 0.7rem; margin: 16px 0; letter-spacing: 3px; } | |
| .result-box { display: none; margin-top: 16px; } | |
| .result-box.show { display: block; } | |
| .token-preview { | |
| background: #0a1510; border: 1px solid #1e4d2a; padding: 8px; | |
| border-radius: 4px; font-size: 0.55rem; color: #4daa72; | |
| word-break: break-all; max-height: 60px; overflow: hidden; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <h1>◈ MAYA TOKEN EXTRACT v3</h1> | |
| <!-- Check if we received a token via URL param --> | |
| <div id="receivedToken" class="hidden"> | |
| <div class="step"> | |
| <span class="step-num">TOKEN RECEIVED!</span> | |
| <div class="token-preview" id="receivedPreview"></div> | |
| <button class="btn" onclick="processReceivedToken()">SAVE TO BRIDGE + TEST</button> | |
| <div class="status" id="receivedStatus"></div> | |
| </div> | |
| </div> | |
| <!-- METHOD 1: Paste token directly --> | |
| <div id="mainUI"> | |
| <div class="step"> | |
| <span class="step-num">STEP 1</span> | |
| <p>Open <b>sesameai.app</b> in your browser. Sign in with Google normally.</p> | |
| <a href="https://sesameai.app" target="_blank" class="btn" style="display:block;text-align:center;text-decoration:none;margin-top:8px;">OPEN SESAMEAI.APP</a> | |
| </div> | |
| <div class="step"> | |
| <span class="step-num">STEP 2</span> | |
| <p>After signing in, tap the button below to copy the extractor script. Then create a <b>new bookmark</b> in your browser, edit it, and paste the script as the URL.</p> | |
| <button class="btn btn-alt" onclick="copyBookmarklet()">COPY EXTRACTOR SCRIPT</button> | |
| <p style="margin-top:8px;font-size:0.7rem;color:#666;"> | |
| Android Chrome: Menu → Bookmarks → ⋮ → Edit → replace URL with copied script<br> | |
| Then go to sesameai.app and tap the bookmark from address bar | |
| </p> | |
| </div> | |
| <div class="step"> | |
| <span class="step-num">STEP 3</span> | |
| <p>OR: After signing in to sesameai.app, paste this in the browser console (if you can access it):</p> | |
| <div class="code-box" id="consoleScript" onclick="copyConsole()"></div> | |
| <button class="btn btn-alt" onclick="copyConsole()">COPY CONSOLE SCRIPT</button> | |
| </div> | |
| <div class="or-line">— OR PASTE TOKEN DIRECTLY —</div> | |
| <div class="step"> | |
| <span class="step-num">MANUAL</span> | |
| <p>If you have the Firebase ID token from DevTools or any other source, paste it here:</p> | |
| <textarea id="manualToken" placeholder="paste Firebase ID token here..."></textarea> | |
| <button class="btn" onclick="processManualToken()">SAVE + TEST TOKEN</button> | |
| </div> | |
| <div class="status" id="mainStatus"></div> | |
| <div class="result-box" id="results"> | |
| <div class="code-box" id="resultsText" style="max-height:300px;font-size:0.6rem;"></div> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| const HF_REPO = 'Melofhell00/maya-memory'; | |
| const HF_TOKEN = atob('aGZfRmVtSHJndHhwcGVQZ3BYblF5eVFsSUlISUVvTXJOQmdPZA=='); | |
| const FK = 'AIzaSyDtC7Uwb5pGAsdmrH2T4Gqdk5Mga07jYPM'; | |
| const THIS_URL = window.location.origin + window.location.pathname; | |
| // Bookmarklet: extracts token from IndexedDB and redirects here with it | |
| const extractorCode = ` | |
| (async()=>{ | |
| try{ | |
| const db=await new Promise((r,j)=>{const q=indexedDB.open('firebaseLocalStorageDb');q.onsuccess=e=>r(e.target.result);q.onerror=j}); | |
| const s=db.transaction('firebaseLocalStorage','readonly').objectStore('firebaseLocalStorage'); | |
| const d=await new Promise((r,j)=>{const q=s.getAll();q.onsuccess=e=>r(e.target.result);q.onerror=j}); | |
| let t='',rt=''; | |
| for(const i of d){ | |
| const m=i&&i.value&&i.value.stsTokenManager; | |
| if(m&&m.accessToken){t=m.accessToken;rt=m.refreshToken||'';break} | |
| } | |
| if(t){ | |
| window.location='${THIS_URL}?t='+encodeURIComponent(t)+'&rt='+encodeURIComponent(rt); | |
| }else{ | |
| alert('No token found in IndexedDB. Are you signed in?'); | |
| } | |
| }catch(e){alert('Error: '+e.message)} | |
| })() | |
| `.trim().replace(/\n/g,''); | |
| const bookmarkletURL = 'javascript:void(' + encodeURIComponent(extractorCode) + ')'; | |
| // Console-friendly version | |
| const consoleCode = ` | |
| (async()=>{ | |
| const db=await new Promise(r=>{const q=indexedDB.open('firebaseLocalStorageDb');q.onsuccess=e=>r(e.target.result)}); | |
| const s=db.transaction('firebaseLocalStorage','readonly').objectStore('firebaseLocalStorage'); | |
| const d=await new Promise(r=>{const q=s.getAll();q.onsuccess=e=>r(e.target.result)}); | |
| for(const i of d){ | |
| const m=i?.value?.stsTokenManager; | |
| if(m?.accessToken){ | |
| console.log('TOKEN:',m.accessToken); | |
| console.log('REFRESH:',m.refreshToken); | |
| prompt('Copy this token:',m.accessToken); | |
| return; | |
| } | |
| } | |
| console.log('No token found'); | |
| })() | |
| `.trim(); | |
| document.getElementById('consoleScript').textContent = consoleCode; | |
| function copyBookmarklet() { | |
| // For mobile, copy the javascript: URL | |
| copyText(bookmarkletURL); | |
| setStatus('mainStatus', 'Copied! Create a bookmark and paste this as the URL.', 'ok'); | |
| } | |
| function copyConsole() { | |
| copyText(consoleCode); | |
| setStatus('mainStatus', 'Copied! Paste in browser console on sesameai.app', 'ok'); | |
| } | |
| function copyText(text) { | |
| if (navigator.clipboard) { | |
| navigator.clipboard.writeText(text).catch(() => fallbackCopy(text)); | |
| } else { | |
| fallbackCopy(text); | |
| } | |
| } | |
| function fallbackCopy(text) { | |
| const ta = document.createElement('textarea'); | |
| ta.value = text; | |
| ta.style.position = 'fixed'; | |
| ta.style.left = '-9999px'; | |
| document.body.appendChild(ta); | |
| ta.select(); | |
| document.execCommand('copy'); | |
| document.body.removeChild(ta); | |
| } | |
| function setStatus(id, msg, type) { | |
| const el = document.getElementById(id); | |
| el.textContent = msg; | |
| el.className = 'status ' + type; | |
| } | |
| // Check URL params for received token | |
| const params = new URLSearchParams(window.location.search); | |
| const receivedT = params.get('t'); | |
| const receivedRT = params.get('rt'); | |
| if (receivedT) { | |
| document.getElementById('receivedToken').classList.remove('hidden'); | |
| document.getElementById('mainUI').style.display = 'none'; | |
| document.getElementById('receivedPreview').textContent = receivedT.substring(0, 100) + '...'; | |
| // Clean URL | |
| window.history.replaceState({}, '', window.location.pathname); | |
| } | |
| async function processReceivedToken() { | |
| await processToken(receivedT, receivedRT); | |
| } | |
| async function processManualToken() { | |
| const token = document.getElementById('manualToken').value.trim(); | |
| if (!token) { | |
| setStatus('mainStatus', 'Paste a token first', 'err'); | |
| return; | |
| } | |
| await processToken(token, ''); | |
| } | |
| async function processToken(idToken, refreshToken) { | |
| const statusId = receivedT ? 'receivedStatus' : 'mainStatus'; | |
| setStatus(statusId, 'Processing...', 'info'); | |
| // Decode JWT | |
| try { | |
| const payload = JSON.parse(atob(idToken.split('.')[1] + '===')); | |
| const provider = payload?.firebase?.sign_in_provider || 'unknown'; | |
| const email = payload?.email || 'unknown'; | |
| const uid = payload?.sub || 'unknown'; | |
| const exp = new Date(payload.exp * 1000).toLocaleString(); | |
| let info = `provider: ${provider} | email: ${email} | uid: ${uid} | expires: ${exp}`; | |
| if (provider !== 'google.com') { | |
| setStatus(statusId, `WARNING: provider is "${provider}" not "google.com" — Sesame will reject this token`, 'err'); | |
| return; | |
| } | |
| setStatus(statusId, info, 'ok'); | |
| } catch(e) { | |
| setStatus(statusId, 'Failed to decode token: ' + e.message, 'err'); | |
| return; | |
| } | |
| // Save to HF bridge | |
| try { | |
| const state = { | |
| refresh_token: refreshToken || '', | |
| last_id_token: idToken.substring(0, 50) + '...', | |
| last_updated: new Date().toISOString(), | |
| source: 'token-extract-v3-bookmarklet', | |
| full_id_token: idToken | |
| }; | |
| const resp = await fetch( | |
| `https://huggingface.co/api/datasets/${HF_REPO}/commit/main`, | |
| { | |
| method: 'POST', | |
| headers: { | |
| 'Authorization': `Bearer ${HF_TOKEN}`, | |
| 'Content-Type': 'application/json' | |
| }, | |
| body: JSON.stringify({ | |
| summary: 'token from bookmarklet ' + new Date().toISOString(), | |
| operations: [{ | |
| op: 'upload', | |
| path_in_repo: 'state.json', | |
| content: btoa(unescape(encodeURIComponent(JSON.stringify(state, null, 2)))) | |
| }] | |
| }) | |
| } | |
| ); | |
| if (resp.ok) { | |
| appendResult('Saved to HF bridge ✓'); | |
| } else { | |
| appendResult('HF save failed: ' + resp.status); | |
| } | |
| } catch(e) { | |
| appendResult('HF save error: ' + e.message); | |
| } | |
| // Test Sesame endpoints | |
| for (const path of ['agents', 'user']) { | |
| try { | |
| const resp = await fetch(`https://sesameai.app/external/${path}`, { | |
| headers: { 'Authorization': 'Bearer ' + idToken } | |
| }); | |
| const text = await resp.text(); | |
| appendResult(`/${path} [${resp.status}]: ${text.substring(0, 500)}`); | |
| } catch(e) { | |
| appendResult(`/${path} error: ${e.message}`); | |
| } | |
| } | |
| // Show full token for copying to Claude | |
| appendResult('\n--- FULL TOKEN (copy to Claude) ---\n' + idToken); | |
| } | |
| function appendResult(text) { | |
| const el = document.getElementById(receivedT ? 'receivedStatus' : 'results'); | |
| if (el.id === 'results') { | |
| el.classList.add('show'); | |
| document.getElementById('resultsText').textContent += text + '\n'; | |
| } else { | |
| el.textContent += '\n' + text; | |
| el.style.whiteSpace = 'pre-wrap'; | |
| el.style.maxHeight = '400px'; | |
| el.style.overflowY = 'auto'; | |
| } | |
| } | |
| </script> | |
| </body> | |
| </html> | |