feat(FN-2976): detect and display external Tailscale funnel tunnels in remo
Merges external Tailscale funnel detection (FN-2976) — adds types, detection logic, status inclusion, kill flow, and a dedicated UI panel for funnel processes started outside Fusion — alongside custom AI providers API routes and a new settings UI section (FN-2965). Fusion-Task-Id: FN-2976
This commit is contained in:
@@ -494,18 +494,29 @@ export function registerSettingsMemoryRoutes(ctx: ApiRoutesContext, deps: Settin
|
||||
const restore = engine?.getRemoteTunnelRestoreDiagnostics();
|
||||
|
||||
const activeProvider = tunnelStatus?.provider ?? settings.remoteAccess?.activeProvider ?? null;
|
||||
const tunnelState = tunnelStatus?.state ?? "stopped";
|
||||
let cloudflaredAvailable: boolean | null = null;
|
||||
if (activeProvider === "cloudflare") {
|
||||
cloudflaredAvailable = await isCloudflaredAvailable();
|
||||
}
|
||||
|
||||
const externalTunnel = tunnelState === "stopped"
|
||||
? await engine?.detectExternalTunnel()
|
||||
: null;
|
||||
|
||||
res.json({
|
||||
provider: activeProvider,
|
||||
state: tunnelStatus?.state ?? "stopped",
|
||||
state: tunnelState,
|
||||
url: tunnelStatus?.url ?? null,
|
||||
lastError: tunnelStatus?.lastError?.message ?? null,
|
||||
lastErrorCode: tunnelStatus?.lastError?.code ?? null,
|
||||
cloudflaredAvailable,
|
||||
externalTunnel: externalTunnel
|
||||
? {
|
||||
provider: externalTunnel.provider,
|
||||
url: externalTunnel.url,
|
||||
}
|
||||
: null,
|
||||
restore: restore ?? {
|
||||
outcome: "skipped",
|
||||
reason: "not_attempted",
|
||||
@@ -634,6 +645,19 @@ export function registerSettingsMemoryRoutes(ctx: ApiRoutesContext, deps: Settin
|
||||
}
|
||||
});
|
||||
|
||||
router.post("/remote/tunnel/kill-external", async (req, res) => {
|
||||
try {
|
||||
const { engine } = await getProjectContext(req);
|
||||
if (engine) {
|
||||
await engine.killExternalTunnel();
|
||||
}
|
||||
res.json({ ok: true });
|
||||
} catch (err: unknown) {
|
||||
if (err instanceof ApiError) throw err;
|
||||
rethrowAsApiError(err, "Failed to kill external remote tunnel");
|
||||
}
|
||||
});
|
||||
|
||||
router.post("/remote/token/persistent/regenerate", async (req, res) => {
|
||||
try {
|
||||
const { store: scopedStore } = await getProjectContext(req);
|
||||
|
||||
Reference in New Issue
Block a user