fluxy-bot 0.7.7 → 0.8.0
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/bin/cli.js +68 -26
- package/dist-fluxy/assets/{fluxy-Bcd5tJrt.js → fluxy-BL_LI7ag.js} +10 -10
- package/dist-fluxy/assets/globals-BFIvNq55.css +1 -0
- package/dist-fluxy/assets/globals-C5RAI3N1.js +18 -0
- package/dist-fluxy/assets/{onboard-BSlNrxVH.js → onboard-B5MmiDn8.js} +1 -1
- package/dist-fluxy/fluxy.html +3 -3
- package/dist-fluxy/onboard.html +3 -3
- package/package.json +1 -1
- package/shared/relay.ts +21 -0
- package/supervisor/chat/OnboardWizard.tsx +367 -32
- package/supervisor/chat/fluxy-main.tsx +10 -0
- package/supervisor/index.ts +101 -0
- package/worker/index.ts +46 -1
- package/dist-fluxy/assets/globals-Bs_wR6rP.css +0 -1
- package/dist-fluxy/assets/globals-CMrTFJSE.js +0 -18
package/bin/cli.js
CHANGED
|
@@ -18,7 +18,11 @@ const BIN_DIR = path.join(DATA_DIR, 'bin');
|
|
|
18
18
|
const CF_PATH = path.join(BIN_DIR, 'cloudflared');
|
|
19
19
|
|
|
20
20
|
const pkg = JSON.parse(fs.readFileSync(path.join(ROOT, 'package.json'), 'utf-8'));
|
|
21
|
-
const
|
|
21
|
+
const args = process.argv.slice(2);
|
|
22
|
+
const command = args[0];
|
|
23
|
+
const subcommand = args[1];
|
|
24
|
+
const flags = new Set(args.filter(a => a.startsWith('--')));
|
|
25
|
+
const HOSTED = flags.has('--hosted');
|
|
22
26
|
|
|
23
27
|
// ── Daemon constants & helpers ──
|
|
24
28
|
|
|
@@ -828,15 +832,18 @@ function bootServer({ onTunnelUp, onReady } = {}) {
|
|
|
828
832
|
// ── Main flows ──
|
|
829
833
|
|
|
830
834
|
async function init() {
|
|
831
|
-
banner();
|
|
835
|
+
if (!HOSTED) banner();
|
|
832
836
|
|
|
833
837
|
createConfig();
|
|
834
838
|
writeVersionFile(pkg.version);
|
|
835
839
|
|
|
836
|
-
//
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
+
// --hosted: non-interactive, quick tunnel, no prompts
|
|
841
|
+
const tunnelMode = HOSTED ? 'quick' : await (async () => {
|
|
842
|
+
console.log('');
|
|
843
|
+
const mode = await chooseTunnelMode();
|
|
844
|
+
console.log('');
|
|
845
|
+
return mode;
|
|
846
|
+
})();
|
|
840
847
|
|
|
841
848
|
// Update config with chosen mode
|
|
842
849
|
const config = JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf-8'));
|
|
@@ -858,6 +865,11 @@ async function init() {
|
|
|
858
865
|
const canDaemon = hasDaemonSupport();
|
|
859
866
|
const hasTunnelInit = tunnelMode !== 'off';
|
|
860
867
|
|
|
868
|
+
// Hosted mode: simple log lines instead of animated stepper
|
|
869
|
+
const log = HOSTED
|
|
870
|
+
? (msg) => console.log(`[fluxy] ${msg}`)
|
|
871
|
+
: null;
|
|
872
|
+
|
|
861
873
|
const steps = [
|
|
862
874
|
'Creating config',
|
|
863
875
|
...(hasTunnelInit ? ['Installing cloudflared'] : []),
|
|
@@ -867,40 +879,53 @@ async function init() {
|
|
|
867
879
|
...(canDaemon ? ['Setting up auto-start daemon'] : []),
|
|
868
880
|
];
|
|
869
881
|
|
|
870
|
-
const stepper = new Stepper(steps);
|
|
871
|
-
stepper.start();
|
|
882
|
+
const stepper = HOSTED ? null : new Stepper(steps);
|
|
883
|
+
if (stepper) stepper.start();
|
|
872
884
|
|
|
873
885
|
// Config already created
|
|
874
|
-
|
|
886
|
+
if (log) log('Config created');
|
|
887
|
+
if (stepper) stepper.advance();
|
|
875
888
|
|
|
876
889
|
// Cloudflared (skip for named — already installed during setup, skip for off — no tunnel)
|
|
877
890
|
if (hasTunnelInit && tunnelMode !== 'named') {
|
|
891
|
+
if (log) log('Installing cloudflared...');
|
|
878
892
|
await installCloudflared();
|
|
893
|
+
if (log) log('Cloudflared ready');
|
|
879
894
|
}
|
|
880
|
-
if (hasTunnelInit) stepper.advance();
|
|
895
|
+
if (hasTunnelInit && stepper) stepper.advance();
|
|
881
896
|
|
|
882
897
|
// Server + Tunnel
|
|
883
|
-
|
|
898
|
+
if (log) log('Starting server...');
|
|
899
|
+
if (stepper) stepper.advance();
|
|
884
900
|
let result;
|
|
885
901
|
try {
|
|
886
902
|
result = await bootServer({
|
|
887
903
|
onTunnelUp: hasTunnelInit ? (url) => {
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
904
|
+
if (log) log(`Tunnel up: ${url}`);
|
|
905
|
+
if (stepper) {
|
|
906
|
+
stepper.advance(); // Connecting tunnel done
|
|
907
|
+
if (config.relay?.url) {
|
|
908
|
+
stepper.setInfo([
|
|
909
|
+
` ${c.dim}Waiting for ${c.reset}${c.white}${config.relay.url.replace('https://', '')}${c.reset}${c.dim} to become reachable (can take up to 2 min)${c.reset}`,
|
|
910
|
+
` ${c.dim}In the meanwhile you can access:${c.reset} ${c.blue}${link(url)}${c.reset}`,
|
|
911
|
+
]);
|
|
912
|
+
}
|
|
895
913
|
}
|
|
896
914
|
} : undefined,
|
|
897
915
|
onReady: hasTunnelInit ? () => {
|
|
898
|
-
|
|
899
|
-
stepper
|
|
916
|
+
if (log) log('Connection verified');
|
|
917
|
+
if (stepper) {
|
|
918
|
+
stepper.setInfo([]);
|
|
919
|
+
stepper.advance(); // Verifying connection done
|
|
920
|
+
}
|
|
900
921
|
} : undefined,
|
|
901
922
|
});
|
|
902
923
|
} catch (err) {
|
|
903
|
-
stepper.finish();
|
|
924
|
+
if (stepper) stepper.finish();
|
|
925
|
+
if (HOSTED) {
|
|
926
|
+
console.error(JSON.stringify({ error: err.message }));
|
|
927
|
+
process.exit(1);
|
|
928
|
+
}
|
|
904
929
|
console.error(`\n ${c.red}Server failed to start:${c.reset}`);
|
|
905
930
|
console.error(` ${c.dim}${err.message}${c.reset}\n`);
|
|
906
931
|
process.exit(1);
|
|
@@ -908,11 +933,13 @@ async function init() {
|
|
|
908
933
|
let { child, tunnelUrl, relayUrl, tunnelFailed, viteWarm } = result;
|
|
909
934
|
|
|
910
935
|
// Wait for Vite to finish pre-transforming all modules (with timeout)
|
|
936
|
+
if (log) log('Preparing dashboard...');
|
|
911
937
|
await Promise.race([viteWarm, new Promise(r => setTimeout(r, 30_000))]);
|
|
912
|
-
stepper.advance();
|
|
938
|
+
if (stepper) stepper.advance();
|
|
913
939
|
|
|
914
940
|
// Install daemon (systemd on Linux, launchd on macOS)
|
|
915
941
|
if (canDaemon) {
|
|
942
|
+
if (log) log('Installing daemon...');
|
|
916
943
|
await killAndWait(child);
|
|
917
944
|
const nodePath = process.execPath;
|
|
918
945
|
const realHome = os.homedir();
|
|
@@ -924,6 +951,7 @@ async function init() {
|
|
|
924
951
|
// Wait for the daemon's supervisor to get a new tunnel URL
|
|
925
952
|
// (the old one died with the temp server we just killed)
|
|
926
953
|
if (res.status === 0 && hasTunnelInit) {
|
|
954
|
+
if (log) log('Waiting for daemon tunnel URL...');
|
|
927
955
|
let daemonTunnelUrl = null;
|
|
928
956
|
for (let i = 0; i < 30; i++) {
|
|
929
957
|
await new Promise((r) => setTimeout(r, 1000));
|
|
@@ -943,8 +971,19 @@ async function init() {
|
|
|
943
971
|
} catch {}
|
|
944
972
|
}
|
|
945
973
|
|
|
946
|
-
stepper
|
|
947
|
-
|
|
974
|
+
if (stepper) {
|
|
975
|
+
stepper.advance();
|
|
976
|
+
stepper.finish();
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
if (HOSTED) {
|
|
980
|
+
// Machine-readable output for the provisioning script
|
|
981
|
+
const result = { tunnelUrl, status: tunnelFailed ? 'tunnel_failed' : 'ok' };
|
|
982
|
+
if (res.status === 0) result.daemon = true;
|
|
983
|
+
console.log(`__HOSTED_READY__=${JSON.stringify(result)}`);
|
|
984
|
+
process.exit(res.status ?? 0);
|
|
985
|
+
}
|
|
986
|
+
|
|
948
987
|
if (!hasTunnelInit) {
|
|
949
988
|
privateNetworkMessage(config.port);
|
|
950
989
|
} else if (tunnelFailed) {
|
|
@@ -961,8 +1000,11 @@ async function init() {
|
|
|
961
1000
|
process.exit(res.status ?? 0);
|
|
962
1001
|
}
|
|
963
1002
|
|
|
964
|
-
stepper.finish();
|
|
965
|
-
if (
|
|
1003
|
+
if (stepper) stepper.finish();
|
|
1004
|
+
if (HOSTED) {
|
|
1005
|
+
const result = { tunnelUrl, status: tunnelFailed ? 'tunnel_failed' : 'ok' };
|
|
1006
|
+
console.log(`__HOSTED_READY__=${JSON.stringify(result)}`);
|
|
1007
|
+
} else if (!hasTunnelInit) {
|
|
966
1008
|
privateNetworkMessage(config.port);
|
|
967
1009
|
} else if (tunnelFailed) {
|
|
968
1010
|
tunnelFailedMessage(tunnelUrl);
|