fluxy-bot 0.5.49 → 0.5.51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-fluxy/assets/{fluxy-DbZm7HVX.js → fluxy-Dc1OmA8X.js} +1 -1
- package/dist-fluxy/assets/{globals-BHyeC8Bo.css → globals-DkRInmdq.css} +1 -1
- package/dist-fluxy/assets/{globals-B1nERNzb.js → globals-USEW-jnB.js} +6 -6
- package/dist-fluxy/assets/{onboard-bonnEh6v.js → onboard-EbXfpdmz.js} +1 -1
- package/dist-fluxy/fluxy.html +4 -4
- package/dist-fluxy/onboard.html +4 -4
- package/package.json +2 -2
- package/supervisor/chat/OnboardWizard.tsx +41 -6
- package/supervisor/chat/fluxy.html +1 -1
- package/supervisor/chat/onboard.html +1 -1
- package/supervisor/chat/src/styles/globals.css +6 -0
- package/supervisor/fluxy-agent.ts +1 -1
- package/supervisor/index.ts +45 -25
- package/supervisor/widget.js +22 -10
- package/workspace/client/index.html +2 -2
- package/workspace/client/src/styles/globals.css +6 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
import{b as o,j as e,R as n,O as r}from"./globals-
|
|
1
|
+
import{b as o,j as e,R as n,O as r}from"./globals-USEW-jnB.js";function a(){const t=()=>{window.parent?.postMessage({type:"fluxy:onboard-complete"},"*")};return e.jsx(r,{onComplete:t,isInitialSetup:!0})}o.createRoot(document.getElementById("root")).render(e.jsx(n.StrictMode,{children:e.jsx(a,{})}));
|
package/dist-fluxy/fluxy.html
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, interactive-widget=resizes-content" />
|
|
6
6
|
<title>Fluxy Chat</title>
|
|
7
|
-
<script type="module" crossorigin src="/fluxy/assets/fluxy-
|
|
8
|
-
<link rel="modulepreload" crossorigin href="/fluxy/assets/globals-
|
|
9
|
-
<link rel="stylesheet" crossorigin href="/fluxy/assets/globals-
|
|
7
|
+
<script type="module" crossorigin src="/fluxy/assets/fluxy-Dc1OmA8X.js"></script>
|
|
8
|
+
<link rel="modulepreload" crossorigin href="/fluxy/assets/globals-USEW-jnB.js">
|
|
9
|
+
<link rel="stylesheet" crossorigin href="/fluxy/assets/globals-DkRInmdq.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body class="bg-background text-foreground">
|
|
12
12
|
<div id="root"></div>
|
package/dist-fluxy/onboard.html
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, interactive-widget=resizes-content" />
|
|
6
6
|
<title>Fluxy Setup</title>
|
|
7
|
-
<script type="module" crossorigin src="/fluxy/assets/onboard-
|
|
8
|
-
<link rel="modulepreload" crossorigin href="/fluxy/assets/globals-
|
|
9
|
-
<link rel="stylesheet" crossorigin href="/fluxy/assets/globals-
|
|
7
|
+
<script type="module" crossorigin src="/fluxy/assets/onboard-EbXfpdmz.js"></script>
|
|
8
|
+
<link rel="modulepreload" crossorigin href="/fluxy/assets/globals-USEW-jnB.js">
|
|
9
|
+
<link rel="stylesheet" crossorigin href="/fluxy/assets/globals-DkRInmdq.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body class="bg-background text-foreground">
|
|
12
12
|
<div id="root"></div>
|
package/package.json
CHANGED
|
@@ -344,13 +344,30 @@ export default function OnboardWizard({ onComplete, isInitialSetup = false, onSa
|
|
|
344
344
|
|
|
345
345
|
/* ── Auth handlers: Anthropic/Claude ── */
|
|
346
346
|
|
|
347
|
+
const openExternal = (url: string) => {
|
|
348
|
+
const isStandalone = window.matchMedia('(display-mode: standalone)').matches
|
|
349
|
+
|| (navigator as any).standalone === true;
|
|
350
|
+
if (isStandalone) {
|
|
351
|
+
// iOS PWA standalone mode blocks window.open — use a temp anchor with target _blank
|
|
352
|
+
const a = document.createElement('a');
|
|
353
|
+
a.href = url;
|
|
354
|
+
a.target = '_blank';
|
|
355
|
+
a.rel = 'noopener noreferrer';
|
|
356
|
+
document.body.appendChild(a);
|
|
357
|
+
a.click();
|
|
358
|
+
document.body.removeChild(a);
|
|
359
|
+
} else {
|
|
360
|
+
window.open(url, '_blank', 'noopener,noreferrer');
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
|
|
347
364
|
const handleAnthropicAuth = async () => {
|
|
348
365
|
setAnthropicError(undefined);
|
|
349
366
|
try {
|
|
350
367
|
const res = await fetch('/api/auth/claude/start', { method: 'POST' });
|
|
351
368
|
const data = await res.json();
|
|
352
369
|
if (data.success && data.authUrl) {
|
|
353
|
-
|
|
370
|
+
openExternal(data.authUrl);
|
|
354
371
|
setOauthStarted(true);
|
|
355
372
|
} else {
|
|
356
373
|
setAnthropicError(data.error || 'Failed to start authentication');
|
|
@@ -415,7 +432,7 @@ export default function OnboardWizard({ onComplete, isInitialSetup = false, onSa
|
|
|
415
432
|
const res = await fetch('/api/auth/codex/start', { method: 'POST' });
|
|
416
433
|
const data = await res.json();
|
|
417
434
|
if (data.success && data.authUrl) {
|
|
418
|
-
|
|
435
|
+
openExternal(data.authUrl);
|
|
419
436
|
} else {
|
|
420
437
|
setOpenaiWaiting(false);
|
|
421
438
|
setOpenaiError(data.error || 'Failed to start authentication');
|
|
@@ -956,8 +973,17 @@ export default function OnboardWizard({ onComplete, isInitialSetup = false, onSa
|
|
|
956
973
|
{provider === 'anthropic' && (
|
|
957
974
|
<div className="space-y-2.5">
|
|
958
975
|
{isConnected && (
|
|
959
|
-
<div className="
|
|
960
|
-
<
|
|
976
|
+
<div className="space-y-2.5">
|
|
977
|
+
<div className="bg-emerald-500/8 border border-emerald-500/15 rounded-lg px-3.5 py-2.5">
|
|
978
|
+
<p className="text-emerald-400/90 text-[12px]">Connected — Anthropic subscription is active.</p>
|
|
979
|
+
</div>
|
|
980
|
+
<button
|
|
981
|
+
onClick={() => { setAuthState((s) => ({ ...s, anthropic: 'idle' })); setOauthStarted(false); setAnthropicCode(''); setAnthropicError(''); }}
|
|
982
|
+
className="w-full py-1.5 text-white/25 text-[11px] hover:text-white/40 transition-colors flex items-center justify-center gap-1.5"
|
|
983
|
+
>
|
|
984
|
+
<RefreshCw className="h-3 w-3" />
|
|
985
|
+
Re-authenticate
|
|
986
|
+
</button>
|
|
961
987
|
</div>
|
|
962
988
|
)}
|
|
963
989
|
|
|
@@ -1039,8 +1065,17 @@ export default function OnboardWizard({ onComplete, isInitialSetup = false, onSa
|
|
|
1039
1065
|
{provider === 'openai' && (
|
|
1040
1066
|
<div className="space-y-2.5">
|
|
1041
1067
|
{isConnected && (
|
|
1042
|
-
<div className="
|
|
1043
|
-
<
|
|
1068
|
+
<div className="space-y-2.5">
|
|
1069
|
+
<div className="bg-emerald-500/8 border border-emerald-500/15 rounded-lg px-3.5 py-2.5">
|
|
1070
|
+
<p className="text-emerald-400/90 text-[12px]">Connected — ChatGPT subscription is active.</p>
|
|
1071
|
+
</div>
|
|
1072
|
+
<button
|
|
1073
|
+
onClick={() => { setAuthState((s) => ({ ...s, openai: 'idle' })); setOpenaiError(''); }}
|
|
1074
|
+
className="w-full py-1.5 text-white/25 text-[11px] hover:text-white/40 transition-colors flex items-center justify-center gap-1.5"
|
|
1075
|
+
>
|
|
1076
|
+
<RefreshCw className="h-3 w-3" />
|
|
1077
|
+
Re-authenticate
|
|
1078
|
+
</button>
|
|
1044
1079
|
</div>
|
|
1045
1080
|
)}
|
|
1046
1081
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, interactive-widget=resizes-content" />
|
|
6
6
|
<title>Fluxy Chat</title>
|
|
7
7
|
</head>
|
|
8
8
|
<body class="bg-background text-foreground">
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, interactive-widget=resizes-content" />
|
|
6
6
|
<title>Fluxy Setup</title>
|
|
7
7
|
</head>
|
|
8
8
|
<body class="bg-background text-foreground">
|
|
@@ -38,11 +38,17 @@
|
|
|
38
38
|
--radius: 0.75rem;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
html {
|
|
42
|
+
touch-action: manipulation;
|
|
43
|
+
-ms-touch-action: manipulation;
|
|
44
|
+
}
|
|
45
|
+
|
|
41
46
|
body {
|
|
42
47
|
background-color: var(--color-background);
|
|
43
48
|
color: var(--color-foreground);
|
|
44
49
|
-webkit-font-smoothing: antialiased;
|
|
45
50
|
-moz-osx-font-smoothing: grayscale;
|
|
51
|
+
overscroll-behavior: none;
|
|
46
52
|
}
|
|
47
53
|
|
|
48
54
|
::selection {
|
|
@@ -146,6 +146,7 @@ export async function startFluxyAgentQuery(
|
|
|
146
146
|
|
|
147
147
|
let fullText = '';
|
|
148
148
|
const usedTools = new Set<string>();
|
|
149
|
+
let stderrBuf = '';
|
|
149
150
|
|
|
150
151
|
// If there are saved files but no inline attachments, append path info to plain text prompt
|
|
151
152
|
let plainPrompt = prompt;
|
|
@@ -188,7 +189,6 @@ export async function startFluxyAgentQuery(
|
|
|
188
189
|
}
|
|
189
190
|
} catch {}
|
|
190
191
|
|
|
191
|
-
let stderrBuf = '';
|
|
192
192
|
const claudeQuery = query({
|
|
193
193
|
prompt: sdkPrompt,
|
|
194
194
|
options: {
|
package/supervisor/index.ts
CHANGED
|
@@ -762,36 +762,20 @@ export async function startSupervisor() {
|
|
|
762
762
|
config.tunnelUrl = tunnelUrl;
|
|
763
763
|
saveConfig(config);
|
|
764
764
|
|
|
765
|
-
//
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
if (config.relay.url) {
|
|
771
|
-
log.ok(`Relay: ${config.relay.url}`);
|
|
772
|
-
console.log(`__RELAY_URL__=${config.relay.url}`);
|
|
773
|
-
}
|
|
774
|
-
} catch (err) {
|
|
775
|
-
log.warn(`Relay: ${err instanceof Error ? err.message : err}`);
|
|
776
|
-
}
|
|
777
|
-
}
|
|
778
|
-
|
|
779
|
-
// Poll until the full relay→tunnel→server chain is actually working.
|
|
780
|
-
// A 502/503 means the relay can't reach the tunnel yet; anything else
|
|
781
|
-
// (200, 401, 403, etc.) means the chain is live.
|
|
782
|
-
const probeUrl = config.relay?.url || tunnelUrl;
|
|
783
|
-
let ready = false;
|
|
784
|
-
log.info(`Readiness probe: polling ${probeUrl}`);
|
|
765
|
+
// Wait for the tunnel to be reachable before telling the relay about it.
|
|
766
|
+
// This prevents the relay from proxying traffic to a tunnel that isn't ready,
|
|
767
|
+
// which would cause 502s for users on the custom domain.
|
|
768
|
+
let tunnelReady = false;
|
|
769
|
+
log.info(`Readiness probe: waiting for tunnel ${tunnelUrl}`);
|
|
785
770
|
for (let i = 0; i < 30; i++) {
|
|
786
771
|
try {
|
|
787
|
-
const res = await fetch(
|
|
772
|
+
const res = await fetch(tunnelUrl + `/api/health?_cb=${Date.now()}`, {
|
|
788
773
|
signal: AbortSignal.timeout(3000),
|
|
789
774
|
headers: { 'Cache-Control': 'no-cache, no-store' },
|
|
790
775
|
});
|
|
791
776
|
log.info(`Readiness probe #${i + 1}: ${res.status}`);
|
|
792
|
-
// Any non-502/503 means the relay is reaching the tunnel
|
|
793
777
|
if (res.status !== 502 && res.status !== 503) {
|
|
794
|
-
|
|
778
|
+
tunnelReady = true;
|
|
795
779
|
break;
|
|
796
780
|
}
|
|
797
781
|
} catch (err) {
|
|
@@ -799,8 +783,22 @@ export async function startSupervisor() {
|
|
|
799
783
|
}
|
|
800
784
|
await new Promise(r => setTimeout(r, 1000));
|
|
801
785
|
}
|
|
802
|
-
if (!
|
|
803
|
-
log.warn('
|
|
786
|
+
if (!tunnelReady) {
|
|
787
|
+
log.warn('Tunnel readiness probe timed out — updating relay anyway');
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
// Now register tunnel URL with relay and start heartbeats
|
|
791
|
+
if (config.relay?.token) {
|
|
792
|
+
try {
|
|
793
|
+
await updateTunnelUrl(config.relay.token, tunnelUrl);
|
|
794
|
+
startHeartbeat(config.relay.token, tunnelUrl);
|
|
795
|
+
if (config.relay.url) {
|
|
796
|
+
log.ok(`Relay: ${config.relay.url}`);
|
|
797
|
+
console.log(`__RELAY_URL__=${config.relay.url}`);
|
|
798
|
+
}
|
|
799
|
+
} catch (err) {
|
|
800
|
+
log.warn(`Relay: ${err instanceof Error ? err.message : err}`);
|
|
801
|
+
}
|
|
804
802
|
}
|
|
805
803
|
console.log('__READY__');
|
|
806
804
|
} catch (err) {
|
|
@@ -826,6 +824,28 @@ export async function startSupervisor() {
|
|
|
826
824
|
log.warn('Tunnel dead, restarting...');
|
|
827
825
|
try {
|
|
828
826
|
const newUrl = await restartTunnel(config.port);
|
|
827
|
+
|
|
828
|
+
// Wait for the new tunnel to be reachable before updating the relay
|
|
829
|
+
log.info(`Waiting for new tunnel to become reachable: ${newUrl}`);
|
|
830
|
+
let tunnelReady = false;
|
|
831
|
+
for (let i = 0; i < 30; i++) {
|
|
832
|
+
try {
|
|
833
|
+
const res = await fetch(newUrl + `/api/health?_cb=${Date.now()}`, {
|
|
834
|
+
signal: AbortSignal.timeout(3000),
|
|
835
|
+
headers: { 'Cache-Control': 'no-cache, no-store' },
|
|
836
|
+
});
|
|
837
|
+
if (res.status !== 502 && res.status !== 503) {
|
|
838
|
+
tunnelReady = true;
|
|
839
|
+
log.info(`Tunnel reachable after ${i + 1} probes`);
|
|
840
|
+
break;
|
|
841
|
+
}
|
|
842
|
+
} catch {}
|
|
843
|
+
await new Promise(r => setTimeout(r, 1000));
|
|
844
|
+
}
|
|
845
|
+
if (!tunnelReady) {
|
|
846
|
+
log.warn('Tunnel readiness probe timed out — updating relay anyway');
|
|
847
|
+
}
|
|
848
|
+
|
|
829
849
|
tunnelUrl = newUrl;
|
|
830
850
|
config.tunnelUrl = newUrl;
|
|
831
851
|
saveConfig(config);
|
package/supervisor/widget.js
CHANGED
|
@@ -40,16 +40,28 @@
|
|
|
40
40
|
bubble.setAttribute('role', 'button');
|
|
41
41
|
bubble.setAttribute('aria-label', 'Open Fluxy chat');
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
43
|
+
// Safari doesn't support WebM alpha — fall back to poster image
|
|
44
|
+
var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent)
|
|
45
|
+
|| (/iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream);
|
|
46
|
+
|
|
47
|
+
if (isSafari) {
|
|
48
|
+
var img = document.createElement('img');
|
|
49
|
+
img.src = '/fluxy_frame1.png';
|
|
50
|
+
img.alt = 'Fluxy';
|
|
51
|
+
img.draggable = false;
|
|
52
|
+
bubble.appendChild(img);
|
|
53
|
+
} else {
|
|
54
|
+
var video = document.createElement('video');
|
|
55
|
+
video.src = '/fluxy_tilts.webm';
|
|
56
|
+
video.poster = '/fluxy_frame1.png';
|
|
57
|
+
video.autoplay = true;
|
|
58
|
+
video.loop = true;
|
|
59
|
+
video.muted = true;
|
|
60
|
+
video.playsInline = true;
|
|
61
|
+
video.setAttribute('playsinline', '');
|
|
62
|
+
video.draggable = false;
|
|
63
|
+
bubble.appendChild(video);
|
|
64
|
+
}
|
|
53
65
|
|
|
54
66
|
// Mark widget present
|
|
55
67
|
bubble.dataset.fluxyWidget = '1';
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, interactive-widget=resizes-content" />
|
|
6
6
|
<meta name="theme-color" content="#212121" />
|
|
7
7
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
8
8
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
if (root && root.children.length === 0) {
|
|
23
23
|
root.innerHTML =
|
|
24
24
|
'<div style="background:#222122;color:#fff;display:flex;flex-direction:column;align-items:center;justify-content:center;height:100dvh;width:100vw;position:fixed;inset:0;z-index:50;font-family:system-ui,-apple-system,sans-serif;text-align:center;padding:24px">' +
|
|
25
|
-
'<
|
|
25
|
+
'<img src="/fluxy_frame1.png" style="height:120px;width:120px;border-radius:50%;object-fit:cover;margin-bottom:32px" alt="Fluxy" />' +
|
|
26
26
|
'<h1 style="font-size:20px;font-weight:600;margin-bottom:8px">Your app crashed</h1>' +
|
|
27
27
|
'<p style="font-size:14px;color:rgba(255,255,255,0.5);max-width:320px;line-height:1.5">Ask the agent to fix it using the chat.</p>' +
|
|
28
28
|
'</div>';
|
|
@@ -38,11 +38,17 @@
|
|
|
38
38
|
--radius: 0.75rem;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
html {
|
|
42
|
+
touch-action: manipulation;
|
|
43
|
+
-ms-touch-action: manipulation;
|
|
44
|
+
}
|
|
45
|
+
|
|
41
46
|
body {
|
|
42
47
|
background-color: var(--color-background);
|
|
43
48
|
color: var(--color-foreground);
|
|
44
49
|
-webkit-font-smoothing: antialiased;
|
|
45
50
|
-moz-osx-font-smoothing: grayscale;
|
|
51
|
+
overscroll-behavior: none;
|
|
46
52
|
}
|
|
47
53
|
|
|
48
54
|
::selection {
|