@wipcomputer/wip-ldm-os 0.4.85-alpha.3 → 0.4.85-alpha.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -2
- package/SKILL.md +136 -14
- package/bin/ldm.js +525 -75
- package/docs/universal-installer/SPEC.md +16 -3
- package/docs/universal-installer/TECHNICAL.md +4 -4
- package/lib/deploy.mjs +104 -20
- package/lib/detect.mjs +35 -4
- package/lib/registry-migrations.mjs +296 -0
- package/package.json +24 -3
- package/scripts/test-boot-hook-registration.mjs +136 -0
- package/scripts/test-boot-payload-trim.mjs +200 -0
- package/scripts/test-crc-agentid-tenant-boundary.mjs +80 -0
- package/scripts/test-crc-e2ee-key-persistence.mjs +150 -0
- package/scripts/test-crc-e2ee-session-route.mjs +129 -0
- package/scripts/test-crc-pair-login-flow.mjs +115 -0
- package/scripts/test-crc-pair-relink-audit-and-rotation.mjs +164 -0
- package/scripts/test-crc-pair-status-poll-token.mjs +73 -0
- package/scripts/test-crc-websocket-abuse-limits.mjs +128 -0
- package/scripts/test-doctor-hook-dedupe.mjs +188 -0
- package/scripts/test-install-prompt-policy.mjs +84 -0
- package/scripts/test-installer-skill-directory.mjs +55 -0
- package/scripts/test-installer-skill-dry-run-destinations.mjs +100 -0
- package/scripts/test-installer-target-self-update.mjs +131 -0
- package/scripts/test-kaleidoscope-onboarding-copy.mjs +170 -0
- package/scripts/test-kaleidoscope-public-stats-baseline.mjs +129 -0
- package/scripts/test-kaleidoscope-qr-authenticator-confirmation.mjs +89 -0
- package/scripts/test-ldm-status-concurrency.mjs +118 -0
- package/scripts/test-ldm-status-timeout.mjs +96 -0
- package/scripts/test-legacy-npm-sources-migration.mjs +460 -0
- package/scripts/test-readme-install-prompt.mjs +66 -0
- package/shared/boot/boot-config.json +18 -8
- package/shared/docs/dev-guide-wipcomputerinc.md.tmpl +5 -4
- package/shared/rules/security.md +4 -0
- package/shared/templates/install-prompt.md +20 -2
- package/src/boot/README.md +24 -1
- package/src/boot/boot-config.json +18 -8
- package/src/boot/boot-hook.mjs +118 -28
- package/src/boot/installer.mjs +33 -10
- package/src/hosted-mcp/.env.example +4 -0
- package/src/hosted-mcp/README.md +37 -0
- package/src/hosted-mcp/app/footer.js +74 -0
- package/src/hosted-mcp/app/kaleidoscope-login.html +1290 -0
- package/src/hosted-mcp/app/pair.html +165 -57
- package/src/hosted-mcp/app/sprites.png +0 -0
- package/src/hosted-mcp/app/wip-logo.png +0 -0
- package/src/hosted-mcp/codex-relay-e2ee-registry.mjs +208 -0
- package/src/hosted-mcp/codex-relay-ws-abuse-limits.mjs +140 -0
- package/src/hosted-mcp/demo/footer.js +2 -2
- package/src/hosted-mcp/demo/index.html +169 -51
- package/src/hosted-mcp/demo/login.html +390 -28
- package/src/hosted-mcp/demo/privacy.html +4 -214
- package/src/hosted-mcp/demo/tos.html +4 -189
- package/src/hosted-mcp/deploy.sh +308 -56
- package/src/hosted-mcp/docs/self-host.md +268 -0
- package/src/hosted-mcp/legal/internet-services/kaleidoscope/index.html +257 -0
- package/src/hosted-mcp/legal/internet-services/terms/site.html +224 -168
- package/src/hosted-mcp/legal/legal-footer.js +75 -0
- package/src/hosted-mcp/legal/legal.css +166 -0
- package/src/hosted-mcp/legal/privacy/en-ww/index.html +4 -221
- package/src/hosted-mcp/legal/privacy/index.html +253 -0
- package/src/hosted-mcp/nginx/codex-relay.conf +25 -0
- package/src/hosted-mcp/nginx/conf.d/redact-logs.conf +60 -0
- package/src/hosted-mcp/nginx/mcp-oauth.conf +58 -0
- package/src/hosted-mcp/nginx/wip.computer.conf +25 -1
- package/src/hosted-mcp/scripts/audit-logs.sh +205 -0
- package/src/hosted-mcp/scripts/verify-deploy.sh +102 -0
- package/src/hosted-mcp/server.mjs +1681 -166
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"@type": "Offer",
|
|
19
19
|
"price": "0",
|
|
20
20
|
"priceCurrency": "USD",
|
|
21
|
-
"description": "Demo with $
|
|
21
|
+
"description": "Demo with $10.00 simulated wallet"
|
|
22
22
|
},
|
|
23
23
|
"author": {
|
|
24
24
|
"@type": "Organization",
|
|
@@ -70,6 +70,10 @@ html, body {
|
|
|
70
70
|
-webkit-font-smoothing: antialiased;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
body.chat-active {
|
|
74
|
+
background: #FFFFFF;
|
|
75
|
+
}
|
|
76
|
+
|
|
73
77
|
@media (min-width: 768px) {
|
|
74
78
|
html, body { overflow: hidden; }
|
|
75
79
|
}
|
|
@@ -200,6 +204,7 @@ html, body {
|
|
|
200
204
|
bottom: 0;
|
|
201
205
|
max-width: 600px;
|
|
202
206
|
margin: 0 auto;
|
|
207
|
+
background: #FFFFFF;
|
|
203
208
|
}
|
|
204
209
|
|
|
205
210
|
.chat-header {
|
|
@@ -210,7 +215,7 @@ html, body {
|
|
|
210
215
|
text-align: center;
|
|
211
216
|
border-bottom: 1px solid rgba(0, 0, 0, 0.06);
|
|
212
217
|
flex-shrink: 0;
|
|
213
|
-
background: rgba(255,
|
|
218
|
+
background: rgba(255, 255, 255, 0.8);
|
|
214
219
|
-webkit-backdrop-filter: saturate(180%) blur(20px);
|
|
215
220
|
backdrop-filter: saturate(180%) blur(20px);
|
|
216
221
|
}
|
|
@@ -287,6 +292,22 @@ html, body {
|
|
|
287
292
|
margin-top: 6px;
|
|
288
293
|
}
|
|
289
294
|
|
|
295
|
+
.bubble a,
|
|
296
|
+
.bubble .chat-link-button {
|
|
297
|
+
color: var(--accent);
|
|
298
|
+
font: inherit;
|
|
299
|
+
text-decoration: underline;
|
|
300
|
+
text-underline-offset: 2px;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
.bubble .chat-link-button {
|
|
304
|
+
display: inline;
|
|
305
|
+
padding: 0;
|
|
306
|
+
border: 0;
|
|
307
|
+
background: transparent;
|
|
308
|
+
cursor: pointer;
|
|
309
|
+
}
|
|
310
|
+
|
|
290
311
|
/* Camera preview circle */
|
|
291
312
|
.camera-container {
|
|
292
313
|
display: flex;
|
|
@@ -477,7 +498,7 @@ html, body {
|
|
|
477
498
|
padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px));
|
|
478
499
|
border-top: 1px solid var(--input-border);
|
|
479
500
|
flex-shrink: 0;
|
|
480
|
-
background:
|
|
501
|
+
background: #FFFFFF;
|
|
481
502
|
}
|
|
482
503
|
|
|
483
504
|
.chat-input-row {
|
|
@@ -574,7 +595,7 @@ html, body {
|
|
|
574
595
|
<!-- ── CHAT PAGE ── -->
|
|
575
596
|
<div class="chat-page" id="chatPage">
|
|
576
597
|
<div class="chat-header" style="position:relative;">
|
|
577
|
-
<
|
|
598
|
+
<button id="kscopeIcon" type="button" onclick="logoutAndSignBackIn()" aria-label="Log out and sign back in" style="cursor:pointer;position:absolute;left:16px;top:50%;transform:translateY(-50%);display:flex;align-items:center;border:0;background:transparent;padding:0;"></button>
|
|
578
599
|
<div class="chat-header-name">Kaleidoscope</div>
|
|
579
600
|
<div class="chat-header-sub"></div>
|
|
580
601
|
</div>
|
|
@@ -593,6 +614,20 @@ html, body {
|
|
|
593
614
|
<canvas id="photoCanvas" style="display:none;"></canvas>
|
|
594
615
|
|
|
595
616
|
<script>
|
|
617
|
+
// Direct /demo entry is not the public start path. The login handoff writes
|
|
618
|
+
// lesa-token before replacing into /demo, so authenticated continuations pass.
|
|
619
|
+
(function gateDirectDemoEntry() {
|
|
620
|
+
var hasDemoToken = false;
|
|
621
|
+
try {
|
|
622
|
+
hasDemoToken = !!sessionStorage.getItem('lesa-token');
|
|
623
|
+
} catch (err) {
|
|
624
|
+
hasDemoToken = false;
|
|
625
|
+
}
|
|
626
|
+
if (!hasDemoToken) {
|
|
627
|
+
location.replace('/login?next=/demo');
|
|
628
|
+
}
|
|
629
|
+
})();
|
|
630
|
+
|
|
596
631
|
// ── WebAuthn Helpers ──
|
|
597
632
|
|
|
598
633
|
function b64urlToBytes(b64url) {
|
|
@@ -687,6 +722,7 @@ async function doCreateAccount() {
|
|
|
687
722
|
if (result.success) {
|
|
688
723
|
sessionStorage.setItem('lesa-token', result.apiKey);
|
|
689
724
|
sessionStorage.setItem('lesa-agent', result.agentId);
|
|
725
|
+
if (result.tenantId) sessionStorage.setItem('lesa-tenant', result.tenantId);
|
|
690
726
|
sessionStorage.setItem('lesa-new-account', 'true');
|
|
691
727
|
setLoginStatus('Account created.', 'success');
|
|
692
728
|
setTimeout(function() { showChat(); }, 400);
|
|
@@ -757,6 +793,7 @@ async function doSignIn() {
|
|
|
757
793
|
if (result.success) {
|
|
758
794
|
sessionStorage.setItem('lesa-token', result.apiKey);
|
|
759
795
|
sessionStorage.setItem('lesa-agent', result.agentId);
|
|
796
|
+
if (result.tenantId) sessionStorage.setItem('lesa-tenant', result.tenantId);
|
|
760
797
|
setLoginStatus('Signed in.', 'success');
|
|
761
798
|
setTimeout(function() { showChat(); }, 400);
|
|
762
799
|
} else {
|
|
@@ -867,7 +904,7 @@ function showAuthButton() {
|
|
|
867
904
|
btn.innerHTML = '<span style="filter:brightness(0) invert(1);"></span> Authorize';
|
|
868
905
|
btn.onclick = function() {
|
|
869
906
|
container.remove();
|
|
870
|
-
addMessage('
|
|
907
|
+
addMessage('Authorizing', 'user');
|
|
871
908
|
doFaceIDAuth();
|
|
872
909
|
};
|
|
873
910
|
container.appendChild(btn);
|
|
@@ -878,17 +915,52 @@ function showAuthButton() {
|
|
|
878
915
|
|
|
879
916
|
// ── Settings ──
|
|
880
917
|
|
|
881
|
-
var WALLET_BALANCE = "$
|
|
918
|
+
var WALLET_BALANCE = "$10.00";
|
|
882
919
|
var IMAGE_COST = "$0.01";
|
|
883
|
-
var IMAGE_BALANCE_AFTER = "$
|
|
920
|
+
var IMAGE_BALANCE_AFTER = "$9.99";
|
|
884
921
|
var IMAGE_API_NAME = "Grok Imagine";
|
|
885
922
|
var IMAGE_API_PROVIDER = "xAI";
|
|
923
|
+
var IS_RETURNING_USER_FLOW = false;
|
|
924
|
+
|
|
925
|
+
async function getWalletSummary() {
|
|
926
|
+
var walletBalance = WALLET_BALANCE;
|
|
927
|
+
var walletCost = IMAGE_COST;
|
|
928
|
+
try {
|
|
929
|
+
var token = sessionStorage.getItem('lesa-token');
|
|
930
|
+
if (!token) return { balance: walletBalance, cost: walletCost };
|
|
931
|
+
var wRes = await fetch('/demo/api/wallet', { headers: { 'Authorization': 'Bearer ' + token } });
|
|
932
|
+
var wData = await wRes.json();
|
|
933
|
+
if (wData.balance) walletBalance = wData.balance;
|
|
934
|
+
if (wData.cost) walletCost = wData.cost;
|
|
935
|
+
} catch {}
|
|
936
|
+
return { balance: walletBalance, cost: walletCost };
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
function currentAccountLabel() {
|
|
940
|
+
return sessionStorage.getItem('lesa-agent') || 'this account';
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
function canonicalAccountId(value) {
|
|
944
|
+
if (typeof value !== 'string') return null;
|
|
945
|
+
var trimmed = value.trim();
|
|
946
|
+
if (!trimmed) return null;
|
|
947
|
+
return trimmed.indexOf('acct:') === 0 ? trimmed.slice(5) : trimmed;
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
function isSameAccountAuthorization(result, activeToken, activeTenant) {
|
|
951
|
+
var sessionAccount = canonicalAccountId(activeTenant);
|
|
952
|
+
var resultAccount = canonicalAccountId(result && result.tenantId);
|
|
953
|
+
if (sessionAccount && resultAccount) {
|
|
954
|
+
return sessionAccount === resultAccount;
|
|
955
|
+
}
|
|
956
|
+
return !!(activeToken && result && result.apiKey === activeToken);
|
|
957
|
+
}
|
|
886
958
|
|
|
887
959
|
// ── Image Prompts ──
|
|
888
960
|
|
|
889
|
-
var PROMPT_PHOTO = "
|
|
961
|
+
var PROMPT_PHOTO = "Create an abstract kaleidoscope image from the colors, light, and shapes in the user's photo. Use mirrored radial symmetry, analog film grain, warm color bleed, soft exposure, organic imperfections, and no text.";
|
|
890
962
|
|
|
891
|
-
var PROMPT_NO_PHOTO = "abstract kaleidoscope
|
|
963
|
+
var PROMPT_NO_PHOTO = "Create an abstract kaleidoscope image with mirrored radial symmetry, analog film grain, warm color bleed, soft exposure, organic imperfections, and no text.";
|
|
892
964
|
|
|
893
965
|
// ── Demo Flow ──
|
|
894
966
|
|
|
@@ -896,16 +968,19 @@ async function startDemo() {
|
|
|
896
968
|
await delay(600);
|
|
897
969
|
var isNew = sessionStorage.getItem('lesa-new-account') === 'true';
|
|
898
970
|
sessionStorage.removeItem('lesa-new-account');
|
|
899
|
-
await lesaSays("Hi, I'm L\u0113sa. Welcome to Kaleidoscope.", 1200);
|
|
900
|
-
await delay(1000);
|
|
901
971
|
if (isNew) {
|
|
902
|
-
|
|
972
|
+
IS_RETURNING_USER_FLOW = false;
|
|
973
|
+
await lesaSays("Hi, I'm L\u0113sa. Welcome to Kaleidoscope.", 1200);
|
|
974
|
+
await delay(1000);
|
|
975
|
+
await lesaSays("You just created an account with a passkey. The passkey lives on your phone.", 1200);
|
|
976
|
+
await lesaSays("Going forward, you can use your phone to log into any Work in Progress Computer service.", 1500);
|
|
977
|
+
await lesaSays("Anytime I need your permission to do something, I'll ask, and you authorize with your fingerprint or face. No passwords. Ever.", 1500);
|
|
978
|
+
await lesaSays("Want to see it in action? I'll try to do something that costs money, and you decide whether to let me.", 1200);
|
|
903
979
|
} else {
|
|
904
|
-
|
|
980
|
+
IS_RETURNING_USER_FLOW = true;
|
|
981
|
+
await lesaSays("Hi, " + currentAccountLabel() + ". Welcome back to Kaleidoscope.", 1200);
|
|
982
|
+
await lesaSays("Do you want to try giving me permission with your device to create something that costs money?", 1200);
|
|
905
983
|
}
|
|
906
|
-
await lesaSays("Going forward, you can use this passkey to log into any Work in Progress Computer service.", 1500);
|
|
907
|
-
await lesaSays("And I can use it too. Anytime I need your permission to do something, I'll ask, and you authorize with your fingerprint or face. No passwords. Ever.", 1500);
|
|
908
|
-
await lesaSays("Want to see it in action? I'll try to do something that costs money, and you decide whether to let me.", 1200);
|
|
909
984
|
|
|
910
985
|
showChoiceButtons([
|
|
911
986
|
{ label: 'Yes, show me', primary: true, action: demoYesShowMe },
|
|
@@ -916,22 +991,16 @@ async function startDemo() {
|
|
|
916
991
|
// ── "Yes, show me" path ──
|
|
917
992
|
|
|
918
993
|
async function demoYesShowMe() {
|
|
919
|
-
var
|
|
920
|
-
|
|
921
|
-
try {
|
|
922
|
-
var token = sessionStorage.getItem('lesa-token');
|
|
923
|
-
var wRes = await fetch('/demo/api/wallet', { headers: { 'Authorization': 'Bearer ' + token } });
|
|
924
|
-
var wData = await wRes.json();
|
|
925
|
-
if (wData.balance) walletBalance = wData.balance;
|
|
926
|
-
if (wData.cost) walletCost = wData.cost;
|
|
927
|
-
} catch {}
|
|
928
|
-
await lesaSays("I have a wallet with " + walletBalance + ". Do I have your permission to spend " + walletCost + " on image generation using the " + IMAGE_API_PROVIDER + " " + IMAGE_API_NAME + " API?", 1000);
|
|
994
|
+
var wallet = await getWalletSummary();
|
|
995
|
+
await lesaSays("I have a wallet with " + wallet.balance + ". Do I have your permission to spend " + wallet.cost + " on image generation using the " + IMAGE_API_PROVIDER + " " + IMAGE_API_NAME + " API?", 1000);
|
|
929
996
|
|
|
930
997
|
showAuthButton();
|
|
931
998
|
}
|
|
932
999
|
|
|
933
1000
|
async function doFaceIDAuth() {
|
|
934
1001
|
showTyping();
|
|
1002
|
+
var activeToken = sessionStorage.getItem('lesa-token');
|
|
1003
|
+
var activeTenant = sessionStorage.getItem('lesa-tenant');
|
|
935
1004
|
|
|
936
1005
|
try {
|
|
937
1006
|
var optRes = await fetch('/webauthn/auth-options', {
|
|
@@ -983,6 +1052,13 @@ async function doFaceIDAuth() {
|
|
|
983
1052
|
return;
|
|
984
1053
|
}
|
|
985
1054
|
|
|
1055
|
+
if (!isSameAccountAuthorization(result, activeToken, activeTenant)) {
|
|
1056
|
+
removeTyping();
|
|
1057
|
+
await lesaSays("That passkey belongs to a different account. This onboarding session is using " + currentAccountLabel() + ". Restart if you want to switch accounts.", 600);
|
|
1058
|
+
showAuthButton();
|
|
1059
|
+
return;
|
|
1060
|
+
}
|
|
1061
|
+
|
|
986
1062
|
removeTyping();
|
|
987
1063
|
await lesaSays("Thanks for authorizing. Let me show you what I can do.", 600);
|
|
988
1064
|
await delay(500);
|
|
@@ -1081,13 +1157,32 @@ async function demoJustMakeOne() {
|
|
|
1081
1157
|
// ── "No thanks" path (skip permissions entirely) ──
|
|
1082
1158
|
|
|
1083
1159
|
async function demoNoThanks() {
|
|
1084
|
-
await
|
|
1085
|
-
|
|
1160
|
+
await showNoThanksFlow();
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
async function showNoThanksFlow() {
|
|
1164
|
+
if (IS_RETURNING_USER_FLOW) {
|
|
1165
|
+
await showReturningUserNoThanksFlow();
|
|
1166
|
+
return;
|
|
1167
|
+
}
|
|
1168
|
+
await lesaSays("No problem. Let me show you something beautiful.", 1000);
|
|
1169
|
+
await generateKaleidoscope(false, { showWalletReceipt: false, showOutro: false });
|
|
1170
|
+
await showApprovedOutro();
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
async function showReturningUserNoThanksFlow() {
|
|
1174
|
+
await lesaSays("No problem. You can come back anytime.", 1000);
|
|
1175
|
+
await lesaSays("At Work in Progress Computer, we are building the future of AI and human interaction.", 1500);
|
|
1176
|
+
await lesaSaysHTML('We look forward to providing you a streamlined experience across all the AIs you use. Follow us on X <a href="https://x.com/wipcomputer" target="_blank" rel="noopener">@wipcomputer</a> to keep up to date on when we release new features.', 1800);
|
|
1177
|
+
await lesaSays("Made in California by WIP Computer, Inc. Learning Dreaming Machines.", 1200);
|
|
1086
1178
|
}
|
|
1087
1179
|
|
|
1088
1180
|
// ── Image generation ──
|
|
1089
1181
|
|
|
1090
|
-
async function generateKaleidoscope(isPhotoPath) {
|
|
1182
|
+
async function generateKaleidoscope(isPhotoPath, options) {
|
|
1183
|
+
options = options || {};
|
|
1184
|
+
var showWalletReceipt = options.showWalletReceipt !== false;
|
|
1185
|
+
var showDefaultOutro = options.showOutro !== false;
|
|
1091
1186
|
var prompt = isPhotoPath ? PROMPT_PHOTO : PROMPT_NO_PHOTO;
|
|
1092
1187
|
|
|
1093
1188
|
// If photo path, analyze the photo with vision to extract colors/mood
|
|
@@ -1104,7 +1199,7 @@ async function generateKaleidoscope(isPhotoPath) {
|
|
|
1104
1199
|
});
|
|
1105
1200
|
var analyzeData = await analyzeRes.json();
|
|
1106
1201
|
if (analyzeData.description) {
|
|
1107
|
-
prompt = "abstract kaleidoscope
|
|
1202
|
+
prompt = "Create an abstract kaleidoscope image from these visual details in the user's photo: " + analyzeData.description + ". Use mirrored radial symmetry, analog film grain, warm color bleed, soft exposure, organic imperfections, and no text.";
|
|
1108
1203
|
}
|
|
1109
1204
|
} catch (e) {
|
|
1110
1205
|
// Vision analysis failed... fall back to original PROMPT_PHOTO
|
|
@@ -1146,10 +1241,12 @@ async function generateKaleidoscope(isPhotoPath) {
|
|
|
1146
1241
|
genBubble.innerHTML = '<img class="kaleidoscope-img" src="' + data.url + '" alt="Your kaleidoscope">';
|
|
1147
1242
|
scrollToBottom();
|
|
1148
1243
|
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1244
|
+
if (showWalletReceipt) {
|
|
1245
|
+
var cost = data.cost || IMAGE_COST;
|
|
1246
|
+
var balance = data.balance || IMAGE_BALANCE_AFTER;
|
|
1247
|
+
await lesaSays("Cost: " + cost + ". Balance: " + balance + ".", 800);
|
|
1248
|
+
}
|
|
1249
|
+
if (showDefaultOutro) await showOutro();
|
|
1153
1250
|
|
|
1154
1251
|
} catch (err) {
|
|
1155
1252
|
loadingDiv.remove();
|
|
@@ -1161,14 +1258,36 @@ async function generateKaleidoscope(isPhotoPath) {
|
|
|
1161
1258
|
}
|
|
1162
1259
|
|
|
1163
1260
|
async function showOutro() {
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
await
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1261
|
+
if (IS_RETURNING_USER_FLOW) {
|
|
1262
|
+
await showReturningUserOutro();
|
|
1263
|
+
return;
|
|
1264
|
+
}
|
|
1265
|
+
await showApprovedOutro();
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
async function showApprovedOutro() {
|
|
1269
|
+
await lesaSays("At Work in Progress Computer, we are building the future of AI and human interaction.", 1500);
|
|
1270
|
+
await lesaSays("We believe permission is a conversation. Your AI asks. You decide. One glance, one tap.", 1800);
|
|
1271
|
+
await lesaSaysHTML('To see how passkeys work across devices, open <a href="https://wip.computer/demo" target="_blank" rel="noopener">https://wip.computer/demo</a> in any web browser on any computer and use your phone to authenticate.', 1800);
|
|
1272
|
+
await lesaSays("You can also click the icon at the top of this chat to log out, and then you can immediately log back in with your phone too.", 1800);
|
|
1273
|
+
await lesaSaysHTML('We look forward to providing you a streamlined experience across all the AIs you use. Follow us on X <a href="https://x.com/wipcomputer" target="_blank" rel="noopener">@wipcomputer</a> to keep up to date on when we release new features.', 1800);
|
|
1274
|
+
await lesaSays("Your passkey will keep working after you leave.", 1200);
|
|
1275
|
+
await lesaSays("Made in California by WIP Computer, Inc. Learning Dreaming Machines.", 1200);
|
|
1276
|
+
}
|
|
1277
|
+
|
|
1278
|
+
async function showReturningUserOutro() {
|
|
1279
|
+
await lesaSays("At Work in Progress Computer, we are building the future of AI and human interaction.", 1500);
|
|
1280
|
+
await lesaSays("We believe permission is a conversation. Your AI asks. You decide. One glance, one tap.", 1800);
|
|
1281
|
+
await lesaSaysHTML('We look forward to providing you a streamlined experience across all the AIs you use. Follow us on X <a href="https://x.com/wipcomputer" target="_blank" rel="noopener">@wipcomputer</a> to keep up to date on when we release new features.', 1800);
|
|
1282
|
+
await lesaSays("Made in California by WIP Computer, Inc. Learning Dreaming Machines.", 1200);
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
function logoutAndSignBackIn() {
|
|
1286
|
+
sessionStorage.removeItem('lesa-token');
|
|
1287
|
+
sessionStorage.removeItem('lesa-agent');
|
|
1288
|
+
sessionStorage.removeItem('lesa-tenant');
|
|
1289
|
+
sessionStorage.removeItem('lesa-new-account');
|
|
1290
|
+
window.location.href = '/login?next=/demo';
|
|
1172
1291
|
}
|
|
1173
1292
|
|
|
1174
1293
|
async function doGameAuth() {
|
|
@@ -1191,7 +1310,7 @@ async function doGameAuth() {
|
|
|
1191
1310
|
removeTyping();
|
|
1192
1311
|
await lesaSays("You are not authorized to play war games with me.", 1200);
|
|
1193
1312
|
}
|
|
1194
|
-
await lesaSays("
|
|
1313
|
+
await lesaSays("Your passkey will continue to work.", 1500);
|
|
1195
1314
|
}
|
|
1196
1315
|
|
|
1197
1316
|
function showAuthButtonForGame() {
|
|
@@ -1203,7 +1322,7 @@ function showAuthButtonForGame() {
|
|
|
1203
1322
|
btn.innerHTML = '<span style="filter:brightness(0) invert(1);"></span> Authorize';
|
|
1204
1323
|
btn.onclick = function() {
|
|
1205
1324
|
container.remove();
|
|
1206
|
-
addMessage('
|
|
1325
|
+
addMessage('Authorizing', 'user');
|
|
1207
1326
|
doGameAuth();
|
|
1208
1327
|
};
|
|
1209
1328
|
container.appendChild(btn);
|
|
@@ -1223,6 +1342,9 @@ function showCSSKaleidoscope(bubble) {
|
|
|
1223
1342
|
|
|
1224
1343
|
function showChat() {
|
|
1225
1344
|
document.getElementById('loginPage').style.display = 'none';
|
|
1345
|
+
document.body.classList.add('chat-active');
|
|
1346
|
+
var footer = document.getElementById('kscope-footer');
|
|
1347
|
+
if (footer) footer.style.display = 'none';
|
|
1226
1348
|
var chatPage = document.getElementById('chatPage');
|
|
1227
1349
|
chatPage.style.display = 'flex';
|
|
1228
1350
|
startDemo();
|
|
@@ -1233,13 +1355,9 @@ if (sessionStorage.getItem('lesa-token')) {
|
|
|
1233
1355
|
showChat();
|
|
1234
1356
|
}
|
|
1235
1357
|
|
|
1236
|
-
//
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
document.getElementById('createBtn').onclick = function() { doSignIn(); };
|
|
1240
|
-
document.getElementById('handleInputWrap').style.display = 'none';
|
|
1241
|
-
document.getElementById('signInBtn').parentElement.style.display = 'none';
|
|
1242
|
-
}
|
|
1358
|
+
// /demo/ always shows the original create-account UI. Do not key off
|
|
1359
|
+
// localStorage["kscope-has-account"] to swap into sign-in mode here;
|
|
1360
|
+
// that coupled /login state to /demo/ rendering.
|
|
1243
1361
|
|
|
1244
1362
|
// Handle send (not used in demo flow, but wired up)
|
|
1245
1363
|
function handleSend() {
|