mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-09-25 04:54:08 -03:00
feat: support reverse-proxy URL subpaths (llama-swap, SwarmUI) (#1122)
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* Base-path helpers for code running inside the ComfyUI page.
|
||||
*
|
||||
* When ComfyUI is served under a URL subpath by a reverse proxy (e.g.
|
||||
* llama-swap serves it at "/comfyui/", SwarmUI at "/ComfyBackendDirect/"),
|
||||
* the ComfyUI SPA always sits at the root of that prefix, so the prefix is
|
||||
* the current pathname without the trailing slash — the same convention the
|
||||
* ComfyUI frontend uses for its own api_base. Proxies strip the prefix and
|
||||
* forward no headers, so the page URL is the only place to learn it.
|
||||
*/
|
||||
|
||||
export function getComfyUIBasePath() {
|
||||
const { pathname } = window.location;
|
||||
return pathname.endsWith("/") ? pathname.slice(0, -1) : pathname;
|
||||
}
|
||||
|
||||
export function lmUrl(path) {
|
||||
return `${getComfyUIBasePath()}${path}`;
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { app } from "../../scripts/app.js";
|
||||
import { api } from "../../scripts/api.js";
|
||||
import { lmUrl } from "./base_path.js";
|
||||
|
||||
// Mirrors the backend resolver (get_lora_info_absolute): a ".ckpt"/".pt"
|
||||
// reference resolves to the same-named .safetensors file. The scanner only
|
||||
@@ -394,7 +395,7 @@ function connectLibraryChangeSocket() {
|
||||
const protocol = window.location.protocol === "https:" ? "wss://" : "ws://";
|
||||
let ws;
|
||||
try {
|
||||
ws = new WebSocket(`${protocol}${window.location.host}/ws/fetch-progress`);
|
||||
ws = new WebSocket(`${protocol}${window.location.host}${lmUrl("/ws/fetch-progress")}`);
|
||||
} catch (error) {
|
||||
return;
|
||||
}
|
||||
@@ -474,7 +475,7 @@ export async function saveRecipeDirectly() {
|
||||
}
|
||||
|
||||
// Send the request to the backend API
|
||||
const response = await fetch('/api/lm/recipes/save-from-widget', {
|
||||
const response = await fetch(lmUrl('/api/lm/recipes/save-from-widget'), {
|
||||
method: 'POST'
|
||||
});
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { api } from "../../scripts/api.js";
|
||||
import { ensureLmStyles } from "./lm_styles_loader.js";
|
||||
import { lmUrl } from "./base_path.js";
|
||||
|
||||
const LICENSE_ICON_PATH = "/loras_static/images/tabler/";
|
||||
const LICENSE_ICON_PATH = lmUrl("/loras_static/images/tabler/");
|
||||
const LICENSE_FLAG_BITS = {
|
||||
allowNoCredit: 1 << 0,
|
||||
allowOnImages: 1 << 1,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { app } from "../../scripts/app.js";
|
||||
import { lmUrl } from "./base_path.js";
|
||||
|
||||
// ============================================================================
|
||||
// Setting IDs and Defaults
|
||||
@@ -55,7 +56,7 @@ const loadWorkflowOptions = async () => {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const response = await fetch("/api/lm/example-workflows");
|
||||
const response = await fetch(lmUrl("/api/lm/example-workflows"));
|
||||
const data = await response.json();
|
||||
if (data.success && data.workflows) {
|
||||
workflowOptionsFull = data.workflows;
|
||||
@@ -81,7 +82,7 @@ const loadTemplateWorkflow = async (templateName) => {
|
||||
const workflow = workflowOptionsFull.find((w) => w.label === templateName);
|
||||
if (workflow && workflow.value) {
|
||||
const workflowResponse = await fetch(
|
||||
`/api/lm/example-workflows/${encodeURIComponent(workflow.value)}`
|
||||
lmUrl(`/api/lm/example-workflows/${encodeURIComponent(workflow.value)}`)
|
||||
);
|
||||
const workflowData = await workflowResponse.json();
|
||||
if (workflowData.success && workflowData.workflow) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { app } from "../../scripts/app.js";
|
||||
import { lmUrl } from "./base_path.js";
|
||||
|
||||
const BUTTON_TOOLTIP = "Launch LoRA Manager (Shift+Click opens in new window)";
|
||||
const LORA_MANAGER_PATH = "/loras";
|
||||
@@ -9,7 +10,7 @@ const BUTTON_GROUP_CLASS = "lora-manager-top-menu-group";
|
||||
const MIN_VERSION_FOR_ACTION_BAR = [1, 33, 9];
|
||||
|
||||
const openLoraManager = (event) => {
|
||||
const url = `${window.location.origin}${LORA_MANAGER_PATH}`;
|
||||
const url = `${window.location.origin}${lmUrl(LORA_MANAGER_PATH)}`;
|
||||
|
||||
if (event.shiftKey) {
|
||||
window.open(url, "_blank", NEW_WINDOW_FEATURES);
|
||||
@@ -29,7 +30,7 @@ const getComfyUIFrontendVersion = async () => {
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch("/system_stats");
|
||||
const response = await fetch(lmUrl("/system_stats"));
|
||||
const data = await response.json();
|
||||
|
||||
if (data?.system?.comfyui_frontend_version) {
|
||||
@@ -80,7 +81,7 @@ const supportsActionBarButtons = async () => {
|
||||
|
||||
const fetchVersionInfo = async () => {
|
||||
try {
|
||||
const response = await fetch("/api/lm/version-info");
|
||||
const response = await fetch(lmUrl("/api/lm/version-info"));
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// ComfyUI extension to track model usage statistics
|
||||
import { app } from "../../scripts/app.js";
|
||||
import { api } from "../../scripts/api.js";
|
||||
import { lmUrl } from "./base_path.js";
|
||||
import { showToast } from "./utils.js";
|
||||
import { getAutoPathCorrectionPreference, getUsageStatisticsPreference } from "./settings.js";
|
||||
|
||||
@@ -40,7 +41,7 @@ app.registerExtension({
|
||||
async updateUsageStats(promptId) {
|
||||
try {
|
||||
// Call backend endpoint with the prompt_id
|
||||
const response = await fetch(`/api/lm/update-usage-stats`, {
|
||||
const response = await fetch(lmUrl(`/api/lm/update-usage-stats`), {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
export const CONVERTED_TYPE = 'converted-widget';
|
||||
import { app } from "../../scripts/app.js";
|
||||
import { AutoComplete } from "./autocomplete.js";
|
||||
import { lmUrl } from "./base_path.js";
|
||||
|
||||
const ROOT_GRAPH_ID = "root";
|
||||
|
||||
@@ -408,7 +409,7 @@ export function updateConnectedTriggerWords(node, loraNames) {
|
||||
return;
|
||||
}
|
||||
|
||||
fetch("/api/lm/loras/get_trigger_words", {
|
||||
fetch(lmUrl("/api/lm/loras/get_trigger_words"), {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
|
||||
@@ -1105,7 +1105,7 @@ to { transform: rotate(360deg);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.last-used-preview[data-v-b940502e] {
|
||||
.last-used-preview[data-v-7db61bc9] {
|
||||
position: absolute;
|
||||
bottom: 100%;
|
||||
right: 0;
|
||||
@@ -1113,7 +1113,7 @@ to { transform: rotate(360deg);
|
||||
z-index: 100;
|
||||
width: 280px;
|
||||
}
|
||||
.last-used-preview__content[data-v-b940502e] {
|
||||
.last-used-preview__content[data-v-7db61bc9] {
|
||||
background: var(--comfy-menu-bg, #1a1a1a);
|
||||
border: 1px solid var(--border-color, #444);
|
||||
border-radius: 6px;
|
||||
@@ -1123,7 +1123,7 @@ to { transform: rotate(360deg);
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
.last-used-preview__item[data-v-b940502e] {
|
||||
.last-used-preview__item[data-v-7db61bc9] {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
@@ -1131,7 +1131,7 @@ to { transform: rotate(360deg);
|
||||
background: var(--comfy-input-bg, #333);
|
||||
border-radius: 6px;
|
||||
}
|
||||
.last-used-preview__thumb[data-v-b940502e] {
|
||||
.last-used-preview__thumb[data-v-7db61bc9] {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
object-fit: cover;
|
||||
@@ -1139,37 +1139,37 @@ to { transform: rotate(360deg);
|
||||
flex-shrink: 0;
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
.last-used-preview__thumb--placeholder[data-v-b940502e] {
|
||||
.last-used-preview__thumb--placeholder[data-v-7db61bc9] {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--fg-color, #fff);
|
||||
opacity: 0.2;
|
||||
}
|
||||
.last-used-preview__thumb--placeholder svg[data-v-b940502e] {
|
||||
.last-used-preview__thumb--placeholder svg[data-v-7db61bc9] {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
.last-used-preview__info[data-v-b940502e] {
|
||||
.last-used-preview__info[data-v-7db61bc9] {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1px;
|
||||
min-width: 0;
|
||||
}
|
||||
.last-used-preview__name[data-v-b940502e] {
|
||||
.last-used-preview__name[data-v-7db61bc9] {
|
||||
font-size: 11px;
|
||||
color: var(--fg-color, #fff);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.last-used-preview__strength[data-v-b940502e] {
|
||||
.last-used-preview__strength[data-v-7db61bc9] {
|
||||
font-size: 10px;
|
||||
color: var(--fg-color, #fff);
|
||||
opacity: 0.5;
|
||||
}
|
||||
.last-used-preview__more[data-v-b940502e] {
|
||||
.last-used-preview__more[data-v-7db61bc9] {
|
||||
font-size: 11px;
|
||||
color: var(--fg-color, #fff);
|
||||
opacity: 0.5;
|
||||
@@ -1957,10 +1957,10 @@ to { transform: rotate(360deg);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.search-container[data-v-83f6f852] {
|
||||
.search-container[data-v-ed10780a] {
|
||||
position: relative;
|
||||
}
|
||||
.search-icon[data-v-83f6f852] {
|
||||
.search-icon[data-v-ed10780a] {
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
top: 50%;
|
||||
@@ -1970,7 +1970,7 @@ to { transform: rotate(360deg);
|
||||
color: var(--fg-color, #fff);
|
||||
opacity: 0.5;
|
||||
}
|
||||
.search-input[data-v-83f6f852] {
|
||||
.search-input[data-v-ed10780a] {
|
||||
width: 100%;
|
||||
padding: 8px 32px;
|
||||
background: var(--comfy-input-bg, #333);
|
||||
@@ -1981,14 +1981,14 @@ to { transform: rotate(360deg);
|
||||
outline: none;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.search-input[data-v-83f6f852]:focus {
|
||||
.search-input[data-v-ed10780a]:focus {
|
||||
border-color: rgba(66, 153, 225, 0.6);
|
||||
}
|
||||
.search-input[data-v-83f6f852]::placeholder {
|
||||
.search-input[data-v-ed10780a]::placeholder {
|
||||
color: var(--fg-color, #fff);
|
||||
opacity: 0.4;
|
||||
}
|
||||
.clear-button[data-v-83f6f852] {
|
||||
.clear-button[data-v-ed10780a] {
|
||||
position: absolute;
|
||||
right: 8px;
|
||||
top: 50%;
|
||||
@@ -2005,22 +2005,22 @@ to { transform: rotate(360deg);
|
||||
opacity: 0.5;
|
||||
transition: opacity 0.15s;
|
||||
}
|
||||
.clear-button[data-v-83f6f852]:hover {
|
||||
.clear-button[data-v-ed10780a]:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
.clear-button svg[data-v-83f6f852] {
|
||||
.clear-button svg[data-v-ed10780a] {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
color: var(--fg-color, #fff);
|
||||
}
|
||||
.lora-list[data-v-83f6f852] {
|
||||
.lora-list[data-v-ed10780a] {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.lora-item[data-v-83f6f852] {
|
||||
.lora-item[data-v-ed10780a] {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
@@ -2030,14 +2030,14 @@ to { transform: rotate(360deg);
|
||||
transition: all 0.15s;
|
||||
border-left: 3px solid transparent;
|
||||
}
|
||||
.lora-item[data-v-83f6f852]:hover {
|
||||
.lora-item[data-v-ed10780a]:hover {
|
||||
background: rgba(66, 153, 225, 0.15);
|
||||
}
|
||||
.lora-item.active[data-v-83f6f852] {
|
||||
.lora-item.active[data-v-ed10780a] {
|
||||
background: rgba(66, 153, 225, 0.25);
|
||||
border-left-color: rgba(66, 153, 225, 0.8);
|
||||
}
|
||||
.lora-index[data-v-83f6f852] {
|
||||
.lora-index[data-v-ed10780a] {
|
||||
font-family: 'SF Mono', 'Roboto Mono', monospace;
|
||||
font-size: 12px;
|
||||
color: rgba(226, 232, 240, 0.5);
|
||||
@@ -2045,7 +2045,7 @@ to { transform: rotate(360deg);
|
||||
text-align: right;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
.lora-name[data-v-83f6f852] {
|
||||
.lora-name[data-v-ed10780a] {
|
||||
flex: 1;
|
||||
font-size: 13px;
|
||||
color: var(--fg-color, #fff);
|
||||
@@ -2053,7 +2053,7 @@ to { transform: rotate(360deg);
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.current-badge[data-v-83f6f852] {
|
||||
.current-badge[data-v-ed10780a] {
|
||||
font-size: 11px;
|
||||
padding: 2px 8px;
|
||||
background: rgba(66, 153, 225, 0.3);
|
||||
@@ -2062,14 +2062,14 @@ to { transform: rotate(360deg);
|
||||
color: rgba(191, 219, 254, 1);
|
||||
font-weight: 500;
|
||||
}
|
||||
.lora-item.no-lora-item .lora-name[data-v-83f6f852] {
|
||||
.lora-item.no-lora-item .lora-name[data-v-ed10780a] {
|
||||
font-style: italic;
|
||||
color: rgba(226, 232, 240, 0.6);
|
||||
}
|
||||
.lora-item.no-lora-item:hover .lora-name[data-v-83f6f852] {
|
||||
.lora-item.no-lora-item:hover .lora-name[data-v-ed10780a] {
|
||||
color: rgba(226, 232, 240, 0.8);
|
||||
}
|
||||
.no-results[data-v-83f6f852] {
|
||||
.no-results[data-v-ed10780a] {
|
||||
padding: 32px 20px;
|
||||
text-align: center;
|
||||
color: var(--fg-color, #fff);
|
||||
@@ -12262,11 +12262,18 @@ const _sfc_main$c = /* @__PURE__ */ defineComponent({
|
||||
}
|
||||
});
|
||||
const FoldersModal = /* @__PURE__ */ _export_sfc(_sfc_main$c, [["__scopeId", "data-v-046dcbf4"]]);
|
||||
function getLmBasePath() {
|
||||
const { pathname } = window.location;
|
||||
return pathname.endsWith("/") ? pathname.slice(0, -1) : pathname;
|
||||
}
|
||||
function lmApiUrl(path) {
|
||||
return `${getLmBasePath()}${path}`;
|
||||
}
|
||||
function useLoraPoolApi() {
|
||||
const isLoading = ref(false);
|
||||
const fetchBaseModels = async (limit = 50) => {
|
||||
try {
|
||||
const response = await fetch(`/api/lm/loras/base-models?limit=${limit}`);
|
||||
const response = await fetch(lmApiUrl(`/api/lm/loras/base-models?limit=${limit}`));
|
||||
const data = await response.json();
|
||||
return data.base_models || [];
|
||||
} catch (error) {
|
||||
@@ -12276,7 +12283,7 @@ function useLoraPoolApi() {
|
||||
};
|
||||
const fetchTags = async (limit = 0) => {
|
||||
try {
|
||||
const response = await fetch(`/api/lm/loras/top-tags?limit=${limit}`);
|
||||
const response = await fetch(lmApiUrl(`/api/lm/loras/top-tags?limit=${limit}`));
|
||||
const data = await response.json();
|
||||
return data.tags || [];
|
||||
} catch (error) {
|
||||
@@ -12286,7 +12293,7 @@ function useLoraPoolApi() {
|
||||
};
|
||||
const fetchFolderTree = async () => {
|
||||
try {
|
||||
const response = await fetch("/api/lm/loras/unified-folder-tree");
|
||||
const response = await fetch(lmApiUrl("/api/lm/loras/unified-folder-tree"));
|
||||
const data = await response.json();
|
||||
return transformFolderTree(data.tree || {});
|
||||
} catch (error) {
|
||||
@@ -12334,7 +12341,7 @@ function useLoraPoolApi() {
|
||||
if (params.namePatternsUseRegex !== void 0) {
|
||||
urlParams.set("name_pattern_use_regex", String(params.namePatternsUseRegex));
|
||||
}
|
||||
const response = await fetch(`/api/lm/loras/list?${urlParams}`);
|
||||
const response = await fetch(lmApiUrl(`/api/lm/loras/list?${urlParams}`));
|
||||
const data = await response.json();
|
||||
return {
|
||||
items: data.items || [],
|
||||
@@ -12682,7 +12689,7 @@ const _sfc_main$a = /* @__PURE__ */ defineComponent({
|
||||
const previewUrls = ref({});
|
||||
const fetchPreviewUrl = async (loraName) => {
|
||||
try {
|
||||
const response = await fetch(`/api/lm/loras/preview-url?name=${encodeURIComponent(loraName)}`);
|
||||
const response = await fetch(lmApiUrl(`/api/lm/loras/preview-url?name=${encodeURIComponent(loraName)}`));
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
if (data.preview_url) {
|
||||
@@ -12732,7 +12739,7 @@ const _sfc_main$a = /* @__PURE__ */ defineComponent({
|
||||
};
|
||||
}
|
||||
});
|
||||
const LastUsedPreview = /* @__PURE__ */ _export_sfc(_sfc_main$a, [["__scopeId", "data-v-b940502e"]]);
|
||||
const LastUsedPreview = /* @__PURE__ */ _export_sfc(_sfc_main$a, [["__scopeId", "data-v-7db61bc9"]]);
|
||||
const _hoisted_1$7 = { class: "slider-handle__value" };
|
||||
const _sfc_main$9 = /* @__PURE__ */ defineComponent({
|
||||
__name: "SingleSlider",
|
||||
@@ -13528,7 +13535,7 @@ function useLoraRandomizerState(widget) {
|
||||
if (poolConfig) {
|
||||
requestBody.pool_config = poolConfig.filters || {};
|
||||
}
|
||||
const response = await fetch("/api/lm/loras/random-sample", {
|
||||
const response = await fetch(lmApiUrl("/api/lm/loras/random-sample"), {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
@@ -14238,7 +14245,7 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
|
||||
};
|
||||
const customPreviewUrlResolver = async (modelName) => {
|
||||
const response = await fetch(
|
||||
`/api/lm/loras/preview-url?name=${encodeURIComponent(modelName)}&license_flags=true`
|
||||
lmApiUrl(`/api/lm/loras/preview-url?name=${encodeURIComponent(modelName)}&license_flags=true`)
|
||||
);
|
||||
if (!response.ok) {
|
||||
throw new Error("Failed to fetch preview URL");
|
||||
@@ -14364,7 +14371,7 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
|
||||
};
|
||||
}
|
||||
});
|
||||
const LoraListModal = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["__scopeId", "data-v-83f6f852"]]);
|
||||
const LoraListModal = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["__scopeId", "data-v-ed10780a"]]);
|
||||
function useLoraCyclerState(widget) {
|
||||
let isRestoring = false;
|
||||
const currentIndex = ref(1);
|
||||
@@ -14491,7 +14498,7 @@ function useLoraCyclerState(widget) {
|
||||
if (poolConfig == null ? void 0 : poolConfig.filters) {
|
||||
requestBody.pool_config = poolConfig.filters;
|
||||
}
|
||||
const response = await fetch("/api/lm/loras/cycler-list", {
|
||||
const response = await fetch(lmApiUrl("/api/lm/loras/cycler-list"), {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
@@ -15898,6 +15905,13 @@ function stripAutocompleteMetadataFromPromptResult(result) {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
function getComfyUIBasePath() {
|
||||
const { pathname } = window.location;
|
||||
return pathname.endsWith("/") ? pathname.slice(0, -1) : pathname;
|
||||
}
|
||||
function lmUrl(path) {
|
||||
return `${getComfyUIBasePath()}${path}`;
|
||||
}
|
||||
const ROOT_GRAPH_ID = "root";
|
||||
const LORA_PROVIDER_NODE_TYPES = [
|
||||
"Lora Stacker (LoraManager)",
|
||||
@@ -16055,7 +16069,7 @@ function updateConnectedTriggerWords(node, loraNames) {
|
||||
if (nodeIds.length === 0) {
|
||||
return;
|
||||
}
|
||||
fetch("/api/lm/loras/get_trigger_words", {
|
||||
fetch(lmUrl("/api/lm/loras/get_trigger_words"), {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,5 +1,6 @@
|
||||
import { app } from "../../scripts/app.js";
|
||||
import { api } from "../../scripts/api.js";
|
||||
import { lmUrl } from "./base_path.js";
|
||||
import { getAllGraphNodes, getNodeReference, getNodeFromGraph, getChildGraphs, chainCallback, getLinkFromGraph } from "./utils.js";
|
||||
import { ensureLmStyles } from "./lm_styles_loader.js";
|
||||
|
||||
@@ -396,7 +397,7 @@ app.registerExtension({
|
||||
}
|
||||
this._lastFingerprint = fingerprint;
|
||||
|
||||
const response = await fetch("/api/lm/register-nodes", {
|
||||
const response = await fetch(lmUrl("/api/lm/register-nodes"), {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
|
||||
Reference in New Issue
Block a user