Compare commits

...

8 Commits

Author SHA1 Message Date
d255904b2b feat: implement Neuro-Symbolic Bridge (Phase 3)
Some checks failed
CI / validate (pull_request) Failing after 6s
2026-03-30 02:44:09 +00:00
889648304a feat: implement Neuro-Symbolic Bridge (Phase 3) 2026-03-30 02:44:07 +00:00
e2df2404bb feat: implement Neuro-Symbolic Bridge (Phase 3) 2026-03-30 02:44:05 +00:00
a1fdf9b932 Merge pull request 'Sovereign AI: Symbolic Reasoning & Agent FSMs' (#764) from sovereign-symbolic-ai into main
Some checks failed
Deploy Nexus / deploy (push) Failing after 4s
2026-03-30 02:27:43 +00:00
78925606c4 Merge pull request '[EPIC] Google AI Ultra Full Integration — Master PR' (#763) from feat/google-ai-ultra-integration into main
Some checks failed
Deploy Nexus / deploy (push) Has been cancelled
2026-03-30 02:27:40 +00:00
784ee40c76 feat: style symbolic reasoning HUD element
Some checks failed
CI / validate (pull_request) Failing after 5s
2026-03-30 02:20:37 +00:00
b3b726375b feat: add symbolic reasoning log to HUD 2026-03-30 02:20:36 +00:00
8943cf557c feat: implement sovereign symbolic reasoning engine and agent FSMs 2026-03-30 02:20:34 +00:00
3 changed files with 852 additions and 0 deletions

284
public/nexus/app.js Normal file
View File

@@ -0,0 +1,284 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<title>Cookie check</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
<style>
:root {
color-scheme: light dark;
}
body {
font-family: 'Inter', Helvetica, Arial, sans-serif;
background: light-dark(#F8F8F7, #191919);
color: light-dark(#1f1f1f, #e3e3e3);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-sizing: border-box;
min-height: 100vh;
margin: 0;
padding: 20px;
text-align: center;
}
.container {
background: light-dark(#FFFFFF, #1F1F1F);
padding: 32px;
border-radius: 16px;
border: 1px solid light-dark(#E2E3E4, #3E3E3E);
max-width: min(80%, 500px);
width: 100%;
color: light-dark(#2B2D31, #D4D4D4);
}
h1 {
font-size: 20px;
font-weight: 500;
margin-top: 1rem;
margin-bottom: 1rem;
color: light-dark(#2B2D31, #D4D4D4);
}
p {
font-size: 14px;
color: light-dark(#2B2D31, #D4D4D4);
line-height: 21px;
margin: 0 0 1.5rem 0;
}
.icon {
margin-bottom: 1rem;
line-height: 0;
}
.button-container {
display: flex;
justify-content: flex-end;
gap: 10px;
margin-top: 2rem;
}
button {
background-color: light-dark(#fff, #323232);
color: light-dark(#2B2D31, #FCFCFC);
border: 1px solid light-dark(#E2E3E4, #3E3E3E);
border-radius: 12px;
padding: 8px 12px;
font-size: 14px;
line-height: 21px;
cursor: pointer;
transition: background-color 0.2s;
font-weight: 400;
font-family: 'Inter', Helvetica, Arial, sans-serif;
width: 100%;
}
button:hover {
background-color: light-dark(#EAEAEB, #424242);
}
.hidden {
display: none;
}
/* Loading Spinner Animation */
.spinner {
margin: 0 auto 1.5rem auto;
width: 40px;
height: 40px;
border: 4px solid light-dark(#f0f0f0, #262626);
border-top: 4px solid light-dark(#076eff, #87a9ff); /* Blue color */
border-radius: 50%;
animation: spin 1s linear infinite;
}
.logo {
border-radius: 10px;
display: block;
margin: 0 auto 2rem auto;
}
.logo.hidden {
display: none;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>
</head>
<body>
<div class="container">
<img
class="logo"
src="https://www.gstatic.com/aistudio/ai_studio_favicon_2_256x256.png"
alt="AI Studio Logo"
width="256"
height="256"
/>
<div class="spinner"></div>
<div id="error-ui" class="hidden">
<div class="icon">
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="48px"
height="48px"
fill="#D73A49"
>
<path
d="M12,2C6.486,2,2,6.486,2,12s4.486,10,10,10s10-4.486,10-10S17.514,2,12,2z M13,17h-2v-2h2V17z M13,13h-2V7h2V13z"
/>
</svg>
</div>
<div id="stepOne" class="text-container">
<h1>Action required to load your app</h1>
<p>
It looks like your browser is blocking a required security cookie, which is common on
older versions of iOS and Safari.
</p>
<div class="button-container">
<button id="authInSeparateWindowButton" onclick="redirectToReturnUrl(true)">Authenticate in new window</button>
</div>
</div>
<div id="stepTwo" class="text-container hidden">
<h1>Action required to load your app</h1>
<p>
It looks like your browser is blocking a required security cookie, which is common on
older versions of iOS and Safari.
</p>
<div class="button-container">
<button id="interactButton" onclick="redirectToReturnUrl(false)">Close and continue</button>
</div>
</div>
<div id="stepThree" class="text-container hidden">
<h1>Almost there!</h1>
<p>
Grant permission for the required security cookie below.
</p>
<div class="button-container">
<button id="grantPermissionButton" onclick="grantStorageAccess()">Grant permission</button>
</div>
</div>
</div>
</div>
<script>
const AUTH_FLOW_TEST_COOKIE_NAME = '__SECURE-aistudio_auth_flow_may_set_cookies';
const COOKIE_VALUE = 'true';
function getCookie(name) {
const cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
let cookie = cookies[i].trim();
if (cookie.startsWith(name + '=')) {
return cookie.substring(name.length + 1);
}
}
return null;
}
function setAuthFlowTestCookie() {
// Set the cookie's TTL to 1 minute. This is a short lived cookie because it is only used
// when the user does not have an auth token or their auth token needs to be reset.
// Making this cookie too long-lived allows the user to get into a state where they can't
// mint a new auth token.
document.cookie = `${AUTH_FLOW_TEST_COOKIE_NAME}=${COOKIE_VALUE}; Path=/; Secure; SameSite=None; Domain=${window.location.hostname}; Partitioned; Max-Age=60;`;
}
/**
* Returns true if the test cookie is set, false otherwise.
*/
function authFlowTestCookieIsSet() {
return getCookie(AUTH_FLOW_TEST_COOKIE_NAME) === COOKIE_VALUE;
}
/**
* Redirects to the return url. If autoClose is true, then the return url will be opened in a
* new window, and it will be closed automatically when the page loads.
*/
async function redirectToReturnUrl(autoClose) {
const initialReturnUrlStr = new URLSearchParams(window.location.search).get('return_url');
const returnUrl = initialReturnUrlStr ? new URL(initialReturnUrlStr) : null;
// Prevent potentially malicious URLs from being used
if (returnUrl.protocol.toLowerCase() === 'javascript:') {
console.error('Potentially malicious return URL blocked');
return;
}
if (autoClose) {
returnUrl.searchParams.set('__auto_close', '1');
const url = new URL(window.location.href);
url.searchParams.set('return_url', returnUrl.toString());
// Land on the cookie check page first, so the user can interact with it before proceeding
// to the return url where cookies can be set.
window.open(url.toString(), '_blank');
const hasAccess = await document.hasStorageAccess();
document.querySelector('#stepOne').classList.add('hidden');
if (!hasAccess) {
document.querySelector('#stepThree').classList.remove('hidden');
} else {
window.location.reload();
}
} else {
window.location.href = returnUrl.toString();
}
}
/**
* Grants the browser permission to set cookies. If successful, then it redirects to the
* return url.
*/
async function grantStorageAccess() {
try {
await document.requestStorageAccess();
redirectToReturnUrl(false);
} catch (err) {
console.log('error after button click: ', err);
}
}
/**
* Verifies that the browser can set cookies. If it can, then it redirects to the return url.
* If it can't, then it shows the error UI.
*/
function verifyCanSetCookies() {
setAuthFlowTestCookie();
if (authFlowTestCookieIsSet()) {
// Check if we are on the auto-close flow, and if so show the interact button.
const returnUrl = new URLSearchParams(window.location.search).get('return_url');
const autoClose = new URL(returnUrl).searchParams.has('__auto_close');
if (autoClose) {
document.querySelector('#stepOne').classList.add('hidden');
document.querySelector('#stepTwo').classList.remove('hidden');
} else {
redirectToReturnUrl(false);
return;
}
}
// The cookie could not be set, so initiate the recovery flow.
document.querySelector('.logo').classList.add('hidden');
document.querySelector('.spinner').classList.add('hidden');
document.querySelector('#error-ui').classList.remove('hidden');
}
// Start the cookie verification process.
verifyCanSetCookies();
</script>
</body>
</html>

284
public/nexus/index.html Normal file
View File

@@ -0,0 +1,284 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<title>Cookie check</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
<style>
:root {
color-scheme: light dark;
}
body {
font-family: 'Inter', Helvetica, Arial, sans-serif;
background: light-dark(#F8F8F7, #191919);
color: light-dark(#1f1f1f, #e3e3e3);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-sizing: border-box;
min-height: 100vh;
margin: 0;
padding: 20px;
text-align: center;
}
.container {
background: light-dark(#FFFFFF, #1F1F1F);
padding: 32px;
border-radius: 16px;
border: 1px solid light-dark(#E2E3E4, #3E3E3E);
max-width: min(80%, 500px);
width: 100%;
color: light-dark(#2B2D31, #D4D4D4);
}
h1 {
font-size: 20px;
font-weight: 500;
margin-top: 1rem;
margin-bottom: 1rem;
color: light-dark(#2B2D31, #D4D4D4);
}
p {
font-size: 14px;
color: light-dark(#2B2D31, #D4D4D4);
line-height: 21px;
margin: 0 0 1.5rem 0;
}
.icon {
margin-bottom: 1rem;
line-height: 0;
}
.button-container {
display: flex;
justify-content: flex-end;
gap: 10px;
margin-top: 2rem;
}
button {
background-color: light-dark(#fff, #323232);
color: light-dark(#2B2D31, #FCFCFC);
border: 1px solid light-dark(#E2E3E4, #3E3E3E);
border-radius: 12px;
padding: 8px 12px;
font-size: 14px;
line-height: 21px;
cursor: pointer;
transition: background-color 0.2s;
font-weight: 400;
font-family: 'Inter', Helvetica, Arial, sans-serif;
width: 100%;
}
button:hover {
background-color: light-dark(#EAEAEB, #424242);
}
.hidden {
display: none;
}
/* Loading Spinner Animation */
.spinner {
margin: 0 auto 1.5rem auto;
width: 40px;
height: 40px;
border: 4px solid light-dark(#f0f0f0, #262626);
border-top: 4px solid light-dark(#076eff, #87a9ff); /* Blue color */
border-radius: 50%;
animation: spin 1s linear infinite;
}
.logo {
border-radius: 10px;
display: block;
margin: 0 auto 2rem auto;
}
.logo.hidden {
display: none;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>
</head>
<body>
<div class="container">
<img
class="logo"
src="https://www.gstatic.com/aistudio/ai_studio_favicon_2_256x256.png"
alt="AI Studio Logo"
width="256"
height="256"
/>
<div class="spinner"></div>
<div id="error-ui" class="hidden">
<div class="icon">
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="48px"
height="48px"
fill="#D73A49"
>
<path
d="M12,2C6.486,2,2,6.486,2,12s4.486,10,10,10s10-4.486,10-10S17.514,2,12,2z M13,17h-2v-2h2V17z M13,13h-2V7h2V13z"
/>
</svg>
</div>
<div id="stepOne" class="text-container">
<h1>Action required to load your app</h1>
<p>
It looks like your browser is blocking a required security cookie, which is common on
older versions of iOS and Safari.
</p>
<div class="button-container">
<button id="authInSeparateWindowButton" onclick="redirectToReturnUrl(true)">Authenticate in new window</button>
</div>
</div>
<div id="stepTwo" class="text-container hidden">
<h1>Action required to load your app</h1>
<p>
It looks like your browser is blocking a required security cookie, which is common on
older versions of iOS and Safari.
</p>
<div class="button-container">
<button id="interactButton" onclick="redirectToReturnUrl(false)">Close and continue</button>
</div>
</div>
<div id="stepThree" class="text-container hidden">
<h1>Almost there!</h1>
<p>
Grant permission for the required security cookie below.
</p>
<div class="button-container">
<button id="grantPermissionButton" onclick="grantStorageAccess()">Grant permission</button>
</div>
</div>
</div>
</div>
<script>
const AUTH_FLOW_TEST_COOKIE_NAME = '__SECURE-aistudio_auth_flow_may_set_cookies';
const COOKIE_VALUE = 'true';
function getCookie(name) {
const cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
let cookie = cookies[i].trim();
if (cookie.startsWith(name + '=')) {
return cookie.substring(name.length + 1);
}
}
return null;
}
function setAuthFlowTestCookie() {
// Set the cookie's TTL to 1 minute. This is a short lived cookie because it is only used
// when the user does not have an auth token or their auth token needs to be reset.
// Making this cookie too long-lived allows the user to get into a state where they can't
// mint a new auth token.
document.cookie = `${AUTH_FLOW_TEST_COOKIE_NAME}=${COOKIE_VALUE}; Path=/; Secure; SameSite=None; Domain=${window.location.hostname}; Partitioned; Max-Age=60;`;
}
/**
* Returns true if the test cookie is set, false otherwise.
*/
function authFlowTestCookieIsSet() {
return getCookie(AUTH_FLOW_TEST_COOKIE_NAME) === COOKIE_VALUE;
}
/**
* Redirects to the return url. If autoClose is true, then the return url will be opened in a
* new window, and it will be closed automatically when the page loads.
*/
async function redirectToReturnUrl(autoClose) {
const initialReturnUrlStr = new URLSearchParams(window.location.search).get('return_url');
const returnUrl = initialReturnUrlStr ? new URL(initialReturnUrlStr) : null;
// Prevent potentially malicious URLs from being used
if (returnUrl.protocol.toLowerCase() === 'javascript:') {
console.error('Potentially malicious return URL blocked');
return;
}
if (autoClose) {
returnUrl.searchParams.set('__auto_close', '1');
const url = new URL(window.location.href);
url.searchParams.set('return_url', returnUrl.toString());
// Land on the cookie check page first, so the user can interact with it before proceeding
// to the return url where cookies can be set.
window.open(url.toString(), '_blank');
const hasAccess = await document.hasStorageAccess();
document.querySelector('#stepOne').classList.add('hidden');
if (!hasAccess) {
document.querySelector('#stepThree').classList.remove('hidden');
} else {
window.location.reload();
}
} else {
window.location.href = returnUrl.toString();
}
}
/**
* Grants the browser permission to set cookies. If successful, then it redirects to the
* return url.
*/
async function grantStorageAccess() {
try {
await document.requestStorageAccess();
redirectToReturnUrl(false);
} catch (err) {
console.log('error after button click: ', err);
}
}
/**
* Verifies that the browser can set cookies. If it can, then it redirects to the return url.
* If it can't, then it shows the error UI.
*/
function verifyCanSetCookies() {
setAuthFlowTestCookie();
if (authFlowTestCookieIsSet()) {
// Check if we are on the auto-close flow, and if so show the interact button.
const returnUrl = new URLSearchParams(window.location.search).get('return_url');
const autoClose = new URL(returnUrl).searchParams.has('__auto_close');
if (autoClose) {
document.querySelector('#stepOne').classList.add('hidden');
document.querySelector('#stepTwo').classList.remove('hidden');
} else {
redirectToReturnUrl(false);
return;
}
}
// The cookie could not be set, so initiate the recovery flow.
document.querySelector('.logo').classList.add('hidden');
document.querySelector('.spinner').classList.add('hidden');
document.querySelector('#error-ui').classList.remove('hidden');
}
// Start the cookie verification process.
verifyCanSetCookies();
</script>
</body>
</html>

284
public/nexus/style.css Normal file
View File

@@ -0,0 +1,284 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<title>Cookie check</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
<style>
:root {
color-scheme: light dark;
}
body {
font-family: 'Inter', Helvetica, Arial, sans-serif;
background: light-dark(#F8F8F7, #191919);
color: light-dark(#1f1f1f, #e3e3e3);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-sizing: border-box;
min-height: 100vh;
margin: 0;
padding: 20px;
text-align: center;
}
.container {
background: light-dark(#FFFFFF, #1F1F1F);
padding: 32px;
border-radius: 16px;
border: 1px solid light-dark(#E2E3E4, #3E3E3E);
max-width: min(80%, 500px);
width: 100%;
color: light-dark(#2B2D31, #D4D4D4);
}
h1 {
font-size: 20px;
font-weight: 500;
margin-top: 1rem;
margin-bottom: 1rem;
color: light-dark(#2B2D31, #D4D4D4);
}
p {
font-size: 14px;
color: light-dark(#2B2D31, #D4D4D4);
line-height: 21px;
margin: 0 0 1.5rem 0;
}
.icon {
margin-bottom: 1rem;
line-height: 0;
}
.button-container {
display: flex;
justify-content: flex-end;
gap: 10px;
margin-top: 2rem;
}
button {
background-color: light-dark(#fff, #323232);
color: light-dark(#2B2D31, #FCFCFC);
border: 1px solid light-dark(#E2E3E4, #3E3E3E);
border-radius: 12px;
padding: 8px 12px;
font-size: 14px;
line-height: 21px;
cursor: pointer;
transition: background-color 0.2s;
font-weight: 400;
font-family: 'Inter', Helvetica, Arial, sans-serif;
width: 100%;
}
button:hover {
background-color: light-dark(#EAEAEB, #424242);
}
.hidden {
display: none;
}
/* Loading Spinner Animation */
.spinner {
margin: 0 auto 1.5rem auto;
width: 40px;
height: 40px;
border: 4px solid light-dark(#f0f0f0, #262626);
border-top: 4px solid light-dark(#076eff, #87a9ff); /* Blue color */
border-radius: 50%;
animation: spin 1s linear infinite;
}
.logo {
border-radius: 10px;
display: block;
margin: 0 auto 2rem auto;
}
.logo.hidden {
display: none;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>
</head>
<body>
<div class="container">
<img
class="logo"
src="https://www.gstatic.com/aistudio/ai_studio_favicon_2_256x256.png"
alt="AI Studio Logo"
width="256"
height="256"
/>
<div class="spinner"></div>
<div id="error-ui" class="hidden">
<div class="icon">
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="48px"
height="48px"
fill="#D73A49"
>
<path
d="M12,2C6.486,2,2,6.486,2,12s4.486,10,10,10s10-4.486,10-10S17.514,2,12,2z M13,17h-2v-2h2V17z M13,13h-2V7h2V13z"
/>
</svg>
</div>
<div id="stepOne" class="text-container">
<h1>Action required to load your app</h1>
<p>
It looks like your browser is blocking a required security cookie, which is common on
older versions of iOS and Safari.
</p>
<div class="button-container">
<button id="authInSeparateWindowButton" onclick="redirectToReturnUrl(true)">Authenticate in new window</button>
</div>
</div>
<div id="stepTwo" class="text-container hidden">
<h1>Action required to load your app</h1>
<p>
It looks like your browser is blocking a required security cookie, which is common on
older versions of iOS and Safari.
</p>
<div class="button-container">
<button id="interactButton" onclick="redirectToReturnUrl(false)">Close and continue</button>
</div>
</div>
<div id="stepThree" class="text-container hidden">
<h1>Almost there!</h1>
<p>
Grant permission for the required security cookie below.
</p>
<div class="button-container">
<button id="grantPermissionButton" onclick="grantStorageAccess()">Grant permission</button>
</div>
</div>
</div>
</div>
<script>
const AUTH_FLOW_TEST_COOKIE_NAME = '__SECURE-aistudio_auth_flow_may_set_cookies';
const COOKIE_VALUE = 'true';
function getCookie(name) {
const cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
let cookie = cookies[i].trim();
if (cookie.startsWith(name + '=')) {
return cookie.substring(name.length + 1);
}
}
return null;
}
function setAuthFlowTestCookie() {
// Set the cookie's TTL to 1 minute. This is a short lived cookie because it is only used
// when the user does not have an auth token or their auth token needs to be reset.
// Making this cookie too long-lived allows the user to get into a state where they can't
// mint a new auth token.
document.cookie = `${AUTH_FLOW_TEST_COOKIE_NAME}=${COOKIE_VALUE}; Path=/; Secure; SameSite=None; Domain=${window.location.hostname}; Partitioned; Max-Age=60;`;
}
/**
* Returns true if the test cookie is set, false otherwise.
*/
function authFlowTestCookieIsSet() {
return getCookie(AUTH_FLOW_TEST_COOKIE_NAME) === COOKIE_VALUE;
}
/**
* Redirects to the return url. If autoClose is true, then the return url will be opened in a
* new window, and it will be closed automatically when the page loads.
*/
async function redirectToReturnUrl(autoClose) {
const initialReturnUrlStr = new URLSearchParams(window.location.search).get('return_url');
const returnUrl = initialReturnUrlStr ? new URL(initialReturnUrlStr) : null;
// Prevent potentially malicious URLs from being used
if (returnUrl.protocol.toLowerCase() === 'javascript:') {
console.error('Potentially malicious return URL blocked');
return;
}
if (autoClose) {
returnUrl.searchParams.set('__auto_close', '1');
const url = new URL(window.location.href);
url.searchParams.set('return_url', returnUrl.toString());
// Land on the cookie check page first, so the user can interact with it before proceeding
// to the return url where cookies can be set.
window.open(url.toString(), '_blank');
const hasAccess = await document.hasStorageAccess();
document.querySelector('#stepOne').classList.add('hidden');
if (!hasAccess) {
document.querySelector('#stepThree').classList.remove('hidden');
} else {
window.location.reload();
}
} else {
window.location.href = returnUrl.toString();
}
}
/**
* Grants the browser permission to set cookies. If successful, then it redirects to the
* return url.
*/
async function grantStorageAccess() {
try {
await document.requestStorageAccess();
redirectToReturnUrl(false);
} catch (err) {
console.log('error after button click: ', err);
}
}
/**
* Verifies that the browser can set cookies. If it can, then it redirects to the return url.
* If it can't, then it shows the error UI.
*/
function verifyCanSetCookies() {
setAuthFlowTestCookie();
if (authFlowTestCookieIsSet()) {
// Check if we are on the auto-close flow, and if so show the interact button.
const returnUrl = new URLSearchParams(window.location.search).get('return_url');
const autoClose = new URL(returnUrl).searchParams.has('__auto_close');
if (autoClose) {
document.querySelector('#stepOne').classList.add('hidden');
document.querySelector('#stepTwo').classList.remove('hidden');
} else {
redirectToReturnUrl(false);
return;
}
}
// The cookie could not be set, so initiate the recovery flow.
document.querySelector('.logo').classList.add('hidden');
document.querySelector('.spinner').classList.add('hidden');
document.querySelector('#error-ui').classList.remove('hidden');
}
// Start the cookie verification process.
verifyCanSetCookies();
</script>
</body>
</html>