@nextclaw/server 0.15.23 → 0.15.25
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/index.d.ts +485 -28
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +515 -40
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Hono } from "hono";
|
|
2
2
|
import { compress } from "hono/compress";
|
|
3
3
|
import { serve } from "@hono/node-server";
|
|
4
|
-
import { AccessManager, PanelAppError, injectUiContentParamsBootstrap, isInboxDeliveryError, isPanelAppError, isPreferenceError, isProjectError, isServiceAppError, isSessionContextCompactionError, isSessionMessageCursorError, isSessionSettingsError } from "@nextclaw/kernel";
|
|
4
|
+
import { AccessManager, PanelAppError, injectUiContentParamsBootstrap, isAppPackageError, isInboxDeliveryError, isPanelAppError, isPreferenceError, isProjectError, isServiceAppError, isSessionContextCompactionError, isSessionMessageCursorError, isSessionSettingsError, isSystemObjectReferenceError } from "@nextclaw/kernel";
|
|
5
5
|
import { WebSocket, WebSocketServer } from "ws";
|
|
6
6
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
7
|
-
import { mkdir, open, readFile, readdir, realpath, stat } from "node:fs/promises";
|
|
7
|
+
import { lstat, mkdir, open, readFile, readdir, realpath, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
8
8
|
import { basename, dirname, extname, isAbsolute, join, parse, relative, resolve, sep } from "node:path";
|
|
9
9
|
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
10
10
|
import * as NextclawCore from "@nextclaw/core";
|
|
@@ -702,6 +702,118 @@ var AppRoutesController = class {
|
|
|
702
702
|
extensionRuntimeStatus = (c) => c.json(ok(this.options.extensions?.getRuntimeStatus?.() ?? []));
|
|
703
703
|
};
|
|
704
704
|
//#endregion
|
|
705
|
+
//#region src/features/app-packages/controllers/app-packages.controller.ts
|
|
706
|
+
var AppPackagesRoutesController = class {
|
|
707
|
+
constructor(manager) {
|
|
708
|
+
this.manager = manager;
|
|
709
|
+
}
|
|
710
|
+
list = async (c) => c.json(ok(await this.manager.listPackages()));
|
|
711
|
+
get = async (c) => {
|
|
712
|
+
try {
|
|
713
|
+
return c.json(ok(await this.manager.getPackage(c.req.param("appId"))));
|
|
714
|
+
} catch (error) {
|
|
715
|
+
return this.handleError(c, error);
|
|
716
|
+
}
|
|
717
|
+
};
|
|
718
|
+
install = async (c) => {
|
|
719
|
+
const body = await readJson(c.req.raw);
|
|
720
|
+
if (!body.ok || !isRecord$2(body.data) || typeof body.data.source !== "string") return c.json(err("INVALID_APP_PACKAGE_INSTALL", "source is required"), 400);
|
|
721
|
+
try {
|
|
722
|
+
return c.json(ok(await this.manager.install(body.data.source, typeof body.data.registryUrl === "string" ? body.data.registryUrl : void 0)));
|
|
723
|
+
} catch (error) {
|
|
724
|
+
return this.handleError(c, error);
|
|
725
|
+
}
|
|
726
|
+
};
|
|
727
|
+
enable = async (c) => {
|
|
728
|
+
try {
|
|
729
|
+
return c.json(ok(await this.manager.enable(c.req.param("appId"))));
|
|
730
|
+
} catch (error) {
|
|
731
|
+
return this.handleError(c, error);
|
|
732
|
+
}
|
|
733
|
+
};
|
|
734
|
+
disable = async (c) => {
|
|
735
|
+
try {
|
|
736
|
+
return c.json(ok(await this.manager.disable(c.req.param("appId"))));
|
|
737
|
+
} catch (error) {
|
|
738
|
+
return this.handleError(c, error);
|
|
739
|
+
}
|
|
740
|
+
};
|
|
741
|
+
update = async (c) => {
|
|
742
|
+
const body = await readJson(c.req.raw);
|
|
743
|
+
if (!body.ok || !isRecord$2(body.data)) return c.json(err("INVALID_APP_PACKAGE_UPDATE", "invalid update request"), 400);
|
|
744
|
+
try {
|
|
745
|
+
return c.json(ok(await this.manager.update(c.req.param("appId"), {
|
|
746
|
+
version: typeof body.data.version === "string" ? body.data.version : void 0,
|
|
747
|
+
registryUrl: typeof body.data.registryUrl === "string" ? body.data.registryUrl : void 0
|
|
748
|
+
})));
|
|
749
|
+
} catch (error) {
|
|
750
|
+
return this.handleError(c, error);
|
|
751
|
+
}
|
|
752
|
+
};
|
|
753
|
+
rollback = async (c) => {
|
|
754
|
+
const body = await readJson(c.req.raw);
|
|
755
|
+
if (!body.ok || !isRecord$2(body.data) || typeof body.data.version !== "string") return c.json(err("INVALID_APP_PACKAGE_ROLLBACK", "version is required"), 400);
|
|
756
|
+
try {
|
|
757
|
+
return c.json(ok(await this.manager.rollback(c.req.param("appId"), body.data.version)));
|
|
758
|
+
} catch (error) {
|
|
759
|
+
return this.handleError(c, error);
|
|
760
|
+
}
|
|
761
|
+
};
|
|
762
|
+
uninstall = async (c) => {
|
|
763
|
+
const body = await readJson(c.req.raw);
|
|
764
|
+
const purgeData = body.ok && isRecord$2(body.data) && body.data.purgeData === true;
|
|
765
|
+
try {
|
|
766
|
+
return c.json(ok(await this.manager.uninstall(c.req.param("appId"), purgeData)));
|
|
767
|
+
} catch (error) {
|
|
768
|
+
return this.handleError(c, error);
|
|
769
|
+
}
|
|
770
|
+
};
|
|
771
|
+
handleError = (c, error) => {
|
|
772
|
+
if (isAppPackageError(error)) {
|
|
773
|
+
const status = error.code === "APP_PACKAGE_NOT_FOUND" ? 404 : error.code === "APP_PACKAGE_CONFLICT" ? 409 : 400;
|
|
774
|
+
return c.json(err(error.code, error.message), status);
|
|
775
|
+
}
|
|
776
|
+
return c.json(err("APP_PACKAGE_OPERATION_FAILED", error instanceof Error ? error.message : String(error)), 400);
|
|
777
|
+
};
|
|
778
|
+
};
|
|
779
|
+
//#endregion
|
|
780
|
+
//#region src/app/controllers/system-object-references.controller.ts
|
|
781
|
+
function readLimit(value) {
|
|
782
|
+
if (value === void 0) return void 0;
|
|
783
|
+
const limit = Number(value);
|
|
784
|
+
return Number.isSafeInteger(limit) && limit >= 1 && limit <= 50 ? limit : null;
|
|
785
|
+
}
|
|
786
|
+
var SystemObjectReferencesRoutesController = class {
|
|
787
|
+
constructor(manager) {
|
|
788
|
+
this.manager = manager;
|
|
789
|
+
}
|
|
790
|
+
list = async (c) => {
|
|
791
|
+
const limit = readLimit(c.req.query("limit"));
|
|
792
|
+
if (limit === null) return c.json(err("INVALID_SYSTEM_OBJECT_QUERY", `limit must be between 1 and 50`), 400);
|
|
793
|
+
try {
|
|
794
|
+
return c.json(ok(await this.manager.listReferences({
|
|
795
|
+
query: c.req.query("query"),
|
|
796
|
+
limit,
|
|
797
|
+
objectType: c.req.query("objectType")
|
|
798
|
+
})));
|
|
799
|
+
} catch (error) {
|
|
800
|
+
if (!isSystemObjectReferenceError(error)) throw error;
|
|
801
|
+
return c.json(err(error.code, error.message), 400);
|
|
802
|
+
}
|
|
803
|
+
};
|
|
804
|
+
resolve = async (c) => {
|
|
805
|
+
const body = await readJson(c.req.raw);
|
|
806
|
+
if (!body.ok || !isRecord$2(body.data) || typeof body.data.uri !== "string" || !body.data.uri.trim()) return c.json(err("INVALID_SYSTEM_OBJECT_REFERENCE", "uri must be a non-empty string"), 400);
|
|
807
|
+
try {
|
|
808
|
+
return c.json(ok(await this.manager.resolveReference(body.data.uri)));
|
|
809
|
+
} catch (error) {
|
|
810
|
+
if (!isSystemObjectReferenceError(error)) throw error;
|
|
811
|
+
const status = error.code === "SYSTEM_OBJECT_NOT_FOUND" ? 404 : 400;
|
|
812
|
+
return c.json(err(error.code, error.message), status);
|
|
813
|
+
}
|
|
814
|
+
};
|
|
815
|
+
};
|
|
816
|
+
//#endregion
|
|
705
817
|
//#region src/features/config/providers/server-builtin-provider.provider.ts
|
|
706
818
|
const SERVER_BUILTIN_PROVIDER_OVERRIDES = [{
|
|
707
819
|
name: "minimax-portal",
|
|
@@ -3081,7 +3193,6 @@ var InboxDeliveriesRoutesController = class {
|
|
|
3081
3193
|
deliveryId
|
|
3082
3194
|
}));
|
|
3083
3195
|
};
|
|
3084
|
-
continueInChat = async (c) => await this.handleManagerAction(c, () => this.manager.continueInChat(c.req.param("deliveryId")));
|
|
3085
3196
|
handleManagerAction = async (c, action) => {
|
|
3086
3197
|
try {
|
|
3087
3198
|
return c.json(ok(await action()));
|
|
@@ -3734,6 +3845,17 @@ function findUnsupportedSkillInstallKind(items) {
|
|
|
3734
3845
|
}
|
|
3735
3846
|
//#endregion
|
|
3736
3847
|
//#region src/features/marketplace/controllers/skill-marketplace.controller.ts
|
|
3848
|
+
const MARKETPLACE_SKILL_LOCAL_CHANGES_ERROR_CODE = "MARKETPLACE_SKILL_LOCAL_CHANGES";
|
|
3849
|
+
function readStructuredError(error) {
|
|
3850
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
3851
|
+
if (!error || typeof error !== "object") return { message };
|
|
3852
|
+
const value = error;
|
|
3853
|
+
return {
|
|
3854
|
+
message,
|
|
3855
|
+
code: typeof value.code === "string" ? value.code : void 0,
|
|
3856
|
+
details: value.details && typeof value.details === "object" && !Array.isArray(value.details) ? value.details : void 0
|
|
3857
|
+
};
|
|
3858
|
+
}
|
|
3737
3859
|
async function installMarketplaceSkill(params) {
|
|
3738
3860
|
const { body, options } = params;
|
|
3739
3861
|
const spec = typeof body.spec === "string" ? body.spec.trim() : "";
|
|
@@ -3903,9 +4025,11 @@ var SkillMarketplaceController = class {
|
|
|
3903
4025
|
});
|
|
3904
4026
|
return c.json(ok(payload));
|
|
3905
4027
|
} catch (error) {
|
|
3906
|
-
const
|
|
4028
|
+
const structuredError = readStructuredError(error);
|
|
4029
|
+
const message = structuredError.message;
|
|
3907
4030
|
if (message.startsWith("INVALID_BODY:")) return c.json(err("INVALID_BODY", message.slice(13)), 400);
|
|
3908
4031
|
if (message.startsWith("NOT_AVAILABLE:")) return c.json(err("NOT_AVAILABLE", message.slice(14)), 503);
|
|
4032
|
+
if (structuredError.code === MARKETPLACE_SKILL_LOCAL_CHANGES_ERROR_CODE) return c.json(err(MARKETPLACE_SKILL_LOCAL_CHANGES_ERROR_CODE, message, structuredError.details), 409);
|
|
3909
4033
|
return c.json(err("MANAGE_FAILED", message), 400);
|
|
3910
4034
|
}
|
|
3911
4035
|
};
|
|
@@ -4839,6 +4963,8 @@ var ServiceAppsRoutesController = class {
|
|
|
4839
4963
|
};
|
|
4840
4964
|
//#endregion
|
|
4841
4965
|
//#region src/app/utils/ncp-session-event-stream.utils.ts
|
|
4966
|
+
const NCP_SESSION_STREAM_HEARTBEAT_INTERVAL_MS = 25e3;
|
|
4967
|
+
const NCP_SESSION_STREAM_HEARTBEAT_FRAME = ": keepalive\n\n";
|
|
4842
4968
|
function readEventSessionId(event) {
|
|
4843
4969
|
const payload = "payload" in event ? event.payload : null;
|
|
4844
4970
|
if (!payload || typeof payload !== "object") return null;
|
|
@@ -4852,8 +4978,13 @@ function createNcpSessionEventStreamResponse(eventBus, payload, signal) {
|
|
|
4852
4978
|
let controller = null;
|
|
4853
4979
|
let closed = false;
|
|
4854
4980
|
let unsubscribe = () => void 0;
|
|
4981
|
+
let heartbeat = null;
|
|
4855
4982
|
const cleanup = () => {
|
|
4856
4983
|
unsubscribe();
|
|
4984
|
+
if (heartbeat) {
|
|
4985
|
+
clearInterval(heartbeat);
|
|
4986
|
+
heartbeat = null;
|
|
4987
|
+
}
|
|
4857
4988
|
signal.removeEventListener("abort", close);
|
|
4858
4989
|
};
|
|
4859
4990
|
const close = () => {
|
|
@@ -4870,6 +5001,9 @@ function createNcpSessionEventStreamResponse(eventBus, payload, signal) {
|
|
|
4870
5001
|
start: (streamController) => {
|
|
4871
5002
|
controller = streamController;
|
|
4872
5003
|
unsubscribe = eventBus.on(eventKeys.ncpEvent, push);
|
|
5004
|
+
heartbeat = setInterval(() => {
|
|
5005
|
+
if (!closed && !signal.aborted) controller?.enqueue(encoder.encode(NCP_SESSION_STREAM_HEARTBEAT_FRAME));
|
|
5006
|
+
}, NCP_SESSION_STREAM_HEARTBEAT_INTERVAL_MS);
|
|
4873
5007
|
signal.addEventListener("abort", close, { once: true });
|
|
4874
5008
|
if (signal.aborted) close();
|
|
4875
5009
|
},
|
|
@@ -5079,6 +5213,28 @@ function isServerPathBrowseError(error) {
|
|
|
5079
5213
|
return error instanceof ServerPathBrowseError;
|
|
5080
5214
|
}
|
|
5081
5215
|
//#endregion
|
|
5216
|
+
//#region src/features/server-path/utils/server-path-search.utils.ts
|
|
5217
|
+
function isServerPathInside(basePath, candidatePath) {
|
|
5218
|
+
const relativePath = relative(basePath, candidatePath);
|
|
5219
|
+
return relativePath === "" || relativePath !== ".." && !relativePath.startsWith(`..${sep}`) && !isAbsolute(relativePath);
|
|
5220
|
+
}
|
|
5221
|
+
function normalizeServerPathRelativePath(value) {
|
|
5222
|
+
return value.split(sep).join("/");
|
|
5223
|
+
}
|
|
5224
|
+
function resolveServerPathSearchScore(entry, query) {
|
|
5225
|
+
if (!query) return 1;
|
|
5226
|
+
const normalizedQuery = query.toLocaleLowerCase();
|
|
5227
|
+
const normalizedName = entry.name.toLocaleLowerCase();
|
|
5228
|
+
const normalizedPath = entry.relativePath.toLocaleLowerCase();
|
|
5229
|
+
if (!normalizedQuery.split(/\s+/).filter(Boolean).every((term) => normalizedPath.includes(term))) return 0;
|
|
5230
|
+
if (normalizedName === normalizedQuery) return 1e3;
|
|
5231
|
+
if (normalizedName.startsWith(normalizedQuery)) return 850;
|
|
5232
|
+
if (normalizedName.includes(normalizedQuery)) return 700;
|
|
5233
|
+
if (normalizedPath.startsWith(normalizedQuery)) return 600;
|
|
5234
|
+
if (normalizedPath.split("/").some((segment) => segment.startsWith(normalizedQuery))) return 550;
|
|
5235
|
+
return 400 - Math.min(normalizedPath.length, 300);
|
|
5236
|
+
}
|
|
5237
|
+
//#endregion
|
|
5082
5238
|
//#region src/features/server-path/utils/server-path-directory.utils.ts
|
|
5083
5239
|
var ServerPathDirectoryCreateError = class extends Error {
|
|
5084
5240
|
constructor(code, message) {
|
|
@@ -5092,28 +5248,46 @@ function normalizeDirectoryName(value) {
|
|
|
5092
5248
|
if (!name || name === "." || name === ".." || name.includes("/") || name.includes("\\")) throw new ServerPathDirectoryCreateError("SERVER_PATH_DIRECTORY_NAME_INVALID", "directory name is invalid");
|
|
5093
5249
|
return name;
|
|
5094
5250
|
}
|
|
5095
|
-
function readFileErrorCode(error) {
|
|
5251
|
+
function readFileErrorCode$1(error) {
|
|
5096
5252
|
return typeof error === "object" && error !== null && "code" in error ? String(error.code ?? "") : void 0;
|
|
5097
5253
|
}
|
|
5098
|
-
|
|
5099
|
-
let parentPath;
|
|
5254
|
+
function resolveDirectoryPath(value) {
|
|
5100
5255
|
try {
|
|
5101
|
-
|
|
5256
|
+
return resolveServerPath({ path: typeof value === "string" ? value : null });
|
|
5102
5257
|
} catch (error) {
|
|
5103
5258
|
if (error instanceof ServerPathResolutionError) throw new ServerPathDirectoryCreateError("SERVER_PATH_PARENT_INVALID", error.message);
|
|
5104
5259
|
throw error;
|
|
5105
5260
|
}
|
|
5261
|
+
}
|
|
5262
|
+
async function assertParentInsideBase(baseValue, parentPath) {
|
|
5263
|
+
if (typeof baseValue !== "string" || !baseValue.trim()) return;
|
|
5264
|
+
const basePath = resolveDirectoryPath(baseValue);
|
|
5265
|
+
if (!isServerPathInside(basePath, parentPath)) throw new ServerPathDirectoryCreateError("SERVER_PATH_PARENT_INVALID", "parent path must stay inside the project root");
|
|
5266
|
+
try {
|
|
5267
|
+
const [realBasePath, realParentPath] = await Promise.all([realpath(basePath), realpath(parentPath)]);
|
|
5268
|
+
if (!isServerPathInside(realBasePath, realParentPath)) throw new ServerPathDirectoryCreateError("SERVER_PATH_PARENT_INVALID", "parent path must stay inside the project root");
|
|
5269
|
+
} catch (error) {
|
|
5270
|
+
if (error instanceof ServerPathDirectoryCreateError) throw error;
|
|
5271
|
+
throw new ServerPathDirectoryCreateError("SERVER_PATH_PARENT_INVALID", "project root and parent path must exist");
|
|
5272
|
+
}
|
|
5273
|
+
}
|
|
5274
|
+
function throwDirectoryCreationError(error) {
|
|
5275
|
+
const code = readFileErrorCode$1(error);
|
|
5276
|
+
if (code === "EEXIST") throw new ServerPathDirectoryCreateError("SERVER_PATH_DIRECTORY_EXISTS", "directory already exists");
|
|
5277
|
+
if (code === "ENOENT") throw new ServerPathDirectoryCreateError("SERVER_PATH_PARENT_NOT_FOUND", "parent directory does not exist");
|
|
5278
|
+
if (code === "ENOTDIR") throw new ServerPathDirectoryCreateError("SERVER_PATH_PARENT_NOT_DIRECTORY", "parent path must point to a directory");
|
|
5279
|
+
if (code === "EACCES" || code === "EPERM" || code === "EROFS") throw new ServerPathDirectoryCreateError("SERVER_PATH_PARENT_NOT_WRITABLE", "parent directory is not writable");
|
|
5280
|
+
throw error;
|
|
5281
|
+
}
|
|
5282
|
+
async function createServerPathDirectory(input) {
|
|
5283
|
+
const parentPath = resolveDirectoryPath(input.parentPath);
|
|
5284
|
+
await assertParentInsideBase(input.basePath, parentPath);
|
|
5106
5285
|
const directoryPath = join(parentPath, normalizeDirectoryName(input.name));
|
|
5107
5286
|
try {
|
|
5108
5287
|
await mkdir(directoryPath);
|
|
5109
5288
|
return { path: directoryPath };
|
|
5110
5289
|
} catch (error) {
|
|
5111
|
-
|
|
5112
|
-
if (code === "EEXIST") throw new ServerPathDirectoryCreateError("SERVER_PATH_DIRECTORY_EXISTS", "directory already exists");
|
|
5113
|
-
if (code === "ENOENT") throw new ServerPathDirectoryCreateError("SERVER_PATH_PARENT_NOT_FOUND", "parent directory does not exist");
|
|
5114
|
-
if (code === "ENOTDIR") throw new ServerPathDirectoryCreateError("SERVER_PATH_PARENT_NOT_DIRECTORY", "parent path must point to a directory");
|
|
5115
|
-
if (code === "EACCES" || code === "EPERM" || code === "EROFS") throw new ServerPathDirectoryCreateError("SERVER_PATH_PARENT_NOT_WRITABLE", "parent directory is not writable");
|
|
5116
|
-
throw error;
|
|
5290
|
+
throwDirectoryCreationError(error);
|
|
5117
5291
|
}
|
|
5118
5292
|
}
|
|
5119
5293
|
function isServerPathDirectoryCreateError(error) {
|
|
@@ -5405,28 +5579,6 @@ function isServerPathContentError(error) {
|
|
|
5405
5579
|
return error instanceof ServerPathContentError;
|
|
5406
5580
|
}
|
|
5407
5581
|
//#endregion
|
|
5408
|
-
//#region src/features/server-path/utils/server-path-search.utils.ts
|
|
5409
|
-
function isServerPathInside(basePath, candidatePath) {
|
|
5410
|
-
const relativePath = relative(basePath, candidatePath);
|
|
5411
|
-
return relativePath === "" || relativePath !== ".." && !relativePath.startsWith(`..${sep}`) && !isAbsolute(relativePath);
|
|
5412
|
-
}
|
|
5413
|
-
function normalizeServerPathRelativePath(value) {
|
|
5414
|
-
return value.split(sep).join("/");
|
|
5415
|
-
}
|
|
5416
|
-
function resolveServerPathSearchScore(entry, query) {
|
|
5417
|
-
if (!query) return 1;
|
|
5418
|
-
const normalizedQuery = query.toLocaleLowerCase();
|
|
5419
|
-
const normalizedName = entry.name.toLocaleLowerCase();
|
|
5420
|
-
const normalizedPath = entry.relativePath.toLocaleLowerCase();
|
|
5421
|
-
if (!normalizedQuery.split(/\s+/).filter(Boolean).every((term) => normalizedPath.includes(term))) return 0;
|
|
5422
|
-
if (normalizedName === normalizedQuery) return 1e3;
|
|
5423
|
-
if (normalizedName.startsWith(normalizedQuery)) return 850;
|
|
5424
|
-
if (normalizedName.includes(normalizedQuery)) return 700;
|
|
5425
|
-
if (normalizedPath.startsWith(normalizedQuery)) return 600;
|
|
5426
|
-
if (normalizedPath.split("/").some((segment) => segment.startsWith(normalizedQuery))) return 550;
|
|
5427
|
-
return 400 - Math.min(normalizedPath.length, 300);
|
|
5428
|
-
}
|
|
5429
|
-
//#endregion
|
|
5430
5582
|
//#region src/features/server-path/services/server-path-search.service.ts
|
|
5431
5583
|
const DEFAULT_RESULT_LIMIT = 50;
|
|
5432
5584
|
const MAX_RESULT_LIMIT = 100;
|
|
@@ -5614,6 +5766,199 @@ function isServerPathSearchError(error) {
|
|
|
5614
5766
|
return error instanceof ServerPathSearchError;
|
|
5615
5767
|
}
|
|
5616
5768
|
//#endregion
|
|
5769
|
+
//#region src/features/server-path/utils/server-path-mutation.utils.ts
|
|
5770
|
+
var ServerPathMutationError = class extends Error {
|
|
5771
|
+
constructor(code, message, details) {
|
|
5772
|
+
super(message);
|
|
5773
|
+
this.code = code;
|
|
5774
|
+
this.details = details;
|
|
5775
|
+
this.name = "ServerPathMutationError";
|
|
5776
|
+
}
|
|
5777
|
+
};
|
|
5778
|
+
function readFileErrorCode(error) {
|
|
5779
|
+
return typeof error === "object" && error !== null && "code" in error ? String(error.code ?? "") : void 0;
|
|
5780
|
+
}
|
|
5781
|
+
function resolveScopedPaths(input) {
|
|
5782
|
+
let basePath;
|
|
5783
|
+
let targetPath;
|
|
5784
|
+
try {
|
|
5785
|
+
basePath = resolveServerPath({ path: typeof input.basePath === "string" ? input.basePath : null });
|
|
5786
|
+
targetPath = resolveServerPath({
|
|
5787
|
+
path: typeof input.targetPath === "string" ? input.targetPath : null,
|
|
5788
|
+
basePath
|
|
5789
|
+
});
|
|
5790
|
+
} catch (error) {
|
|
5791
|
+
if (error instanceof ServerPathResolutionError) throw new ServerPathMutationError("SERVER_PATH_BASE_INVALID", error.message);
|
|
5792
|
+
throw error;
|
|
5793
|
+
}
|
|
5794
|
+
if (!isServerPathInside(basePath, targetPath)) throw new ServerPathMutationError("SERVER_PATH_OUTSIDE_BASE", "target path must stay inside the project root");
|
|
5795
|
+
if (!input.allowRoot && targetPath === basePath) throw new ServerPathMutationError("SERVER_PATH_ROOT_PROTECTED", "the project root cannot be deleted");
|
|
5796
|
+
return {
|
|
5797
|
+
basePath,
|
|
5798
|
+
targetPath
|
|
5799
|
+
};
|
|
5800
|
+
}
|
|
5801
|
+
async function resolveRealBasePath(basePath) {
|
|
5802
|
+
try {
|
|
5803
|
+
const resolved = await realpath(basePath);
|
|
5804
|
+
if (!(await stat(resolved)).isDirectory()) throw new ServerPathMutationError("SERVER_PATH_BASE_INVALID", "project root must point to a directory");
|
|
5805
|
+
return resolved;
|
|
5806
|
+
} catch (error) {
|
|
5807
|
+
if (error instanceof ServerPathMutationError) throw error;
|
|
5808
|
+
throw new ServerPathMutationError("SERVER_PATH_BASE_INVALID", "project root does not exist or is not accessible");
|
|
5809
|
+
}
|
|
5810
|
+
}
|
|
5811
|
+
async function assertExistingPathInsideRealBase(params) {
|
|
5812
|
+
const [realBasePath, realTargetPath] = await Promise.all([resolveRealBasePath(params.basePath), realpath(params.targetPath).catch(() => null)]);
|
|
5813
|
+
if (!realTargetPath) throw new ServerPathMutationError("SERVER_PATH_ENTRY_NOT_FOUND", "target path does not exist");
|
|
5814
|
+
if (!isServerPathInside(realBasePath, realTargetPath)) throw new ServerPathMutationError("SERVER_PATH_OUTSIDE_BASE", "target path must stay inside the project root");
|
|
5815
|
+
}
|
|
5816
|
+
function normalizeEntryName(value) {
|
|
5817
|
+
const name = typeof value === "string" ? value.trim() : "";
|
|
5818
|
+
if (!name || name === "." || name === ".." || name.includes("/") || name.includes("\\") || name.includes("\0") || basename(name) !== name) throw new ServerPathMutationError("SERVER_PATH_FILE_NAME_INVALID", "entry name is invalid");
|
|
5819
|
+
return name;
|
|
5820
|
+
}
|
|
5821
|
+
async function createServerPathFile(input) {
|
|
5822
|
+
const { basePath, targetPath: parentPath } = resolveScopedPaths({
|
|
5823
|
+
basePath: input.basePath,
|
|
5824
|
+
targetPath: input.parentPath,
|
|
5825
|
+
allowRoot: true
|
|
5826
|
+
});
|
|
5827
|
+
await assertExistingPathInsideRealBase({
|
|
5828
|
+
basePath,
|
|
5829
|
+
targetPath: parentPath
|
|
5830
|
+
});
|
|
5831
|
+
if (!(await stat(parentPath).catch(() => null))?.isDirectory()) throw new ServerPathMutationError("SERVER_PATH_TARGET_NOT_DIRECTORY", "file parent must point to a directory");
|
|
5832
|
+
const name = normalizeEntryName(input.name);
|
|
5833
|
+
const path = join(parentPath, name);
|
|
5834
|
+
try {
|
|
5835
|
+
await writeFile(path, "", { flag: "wx" });
|
|
5836
|
+
} catch (error) {
|
|
5837
|
+
const code = readFileErrorCode(error);
|
|
5838
|
+
if (code === "EEXIST") throw new ServerPathMutationError("SERVER_PATH_FILE_EXISTS", "target file already exists");
|
|
5839
|
+
if (code === "EACCES" || code === "EPERM" || code === "EROFS") throw new ServerPathMutationError("SERVER_PATH_TARGET_NOT_WRITABLE", "file parent is not writable");
|
|
5840
|
+
throw error;
|
|
5841
|
+
}
|
|
5842
|
+
return {
|
|
5843
|
+
name,
|
|
5844
|
+
path,
|
|
5845
|
+
kind: "file"
|
|
5846
|
+
};
|
|
5847
|
+
}
|
|
5848
|
+
async function renameServerPathEntry(input) {
|
|
5849
|
+
const { basePath, targetPath } = resolveScopedPaths({
|
|
5850
|
+
basePath: input.basePath,
|
|
5851
|
+
targetPath: input.path
|
|
5852
|
+
});
|
|
5853
|
+
await assertExistingPathInsideRealBase({
|
|
5854
|
+
basePath,
|
|
5855
|
+
targetPath
|
|
5856
|
+
});
|
|
5857
|
+
const entryStats = await lstat(targetPath).catch(() => null);
|
|
5858
|
+
if (!entryStats) throw new ServerPathMutationError("SERVER_PATH_ENTRY_NOT_FOUND", "target path does not exist");
|
|
5859
|
+
const name = normalizeEntryName(input.name);
|
|
5860
|
+
const path = join(resolve(targetPath, ".."), name);
|
|
5861
|
+
if (!isServerPathInside(basePath, path)) throw new ServerPathMutationError("SERVER_PATH_OUTSIDE_BASE", "target path must stay inside the project root");
|
|
5862
|
+
if (await lstat(path).then(() => true).catch(() => false)) throw new ServerPathMutationError("SERVER_PATH_FILE_EXISTS", "target entry already exists");
|
|
5863
|
+
try {
|
|
5864
|
+
await rename(targetPath, path);
|
|
5865
|
+
} catch (error) {
|
|
5866
|
+
const code = readFileErrorCode(error);
|
|
5867
|
+
if (code === "EACCES" || code === "EPERM" || code === "EROFS") throw new ServerPathMutationError("SERVER_PATH_TARGET_NOT_WRITABLE", "target path is not writable");
|
|
5868
|
+
throw error;
|
|
5869
|
+
}
|
|
5870
|
+
return {
|
|
5871
|
+
oldPath: targetPath,
|
|
5872
|
+
path,
|
|
5873
|
+
name,
|
|
5874
|
+
kind: entryStats.isDirectory() ? "directory" : "file"
|
|
5875
|
+
};
|
|
5876
|
+
}
|
|
5877
|
+
async function deleteServerPathEntry(input) {
|
|
5878
|
+
const { basePath, targetPath } = resolveScopedPaths({
|
|
5879
|
+
basePath: input.basePath,
|
|
5880
|
+
targetPath: input.path
|
|
5881
|
+
});
|
|
5882
|
+
await assertExistingPathInsideRealBase({
|
|
5883
|
+
basePath,
|
|
5884
|
+
targetPath
|
|
5885
|
+
});
|
|
5886
|
+
let entryStats;
|
|
5887
|
+
try {
|
|
5888
|
+
entryStats = await lstat(targetPath);
|
|
5889
|
+
} catch {
|
|
5890
|
+
throw new ServerPathMutationError("SERVER_PATH_ENTRY_NOT_FOUND", "target path does not exist");
|
|
5891
|
+
}
|
|
5892
|
+
const kind = entryStats.isDirectory() ? "directory" : "file";
|
|
5893
|
+
try {
|
|
5894
|
+
await rm(targetPath, {
|
|
5895
|
+
recursive: kind === "directory",
|
|
5896
|
+
force: false
|
|
5897
|
+
});
|
|
5898
|
+
} catch (error) {
|
|
5899
|
+
const code = readFileErrorCode(error);
|
|
5900
|
+
if (code === "ENOENT") throw new ServerPathMutationError("SERVER_PATH_ENTRY_NOT_FOUND", "target path does not exist");
|
|
5901
|
+
if (code === "EACCES" || code === "EPERM" || code === "EROFS") throw new ServerPathMutationError("SERVER_PATH_TARGET_NOT_WRITABLE", "target path is not writable");
|
|
5902
|
+
throw error;
|
|
5903
|
+
}
|
|
5904
|
+
return {
|
|
5905
|
+
path: targetPath,
|
|
5906
|
+
kind
|
|
5907
|
+
};
|
|
5908
|
+
}
|
|
5909
|
+
async function uploadServerPathFiles(input) {
|
|
5910
|
+
const { basePath, targetPath } = resolveScopedPaths({
|
|
5911
|
+
basePath: input.basePath,
|
|
5912
|
+
targetPath: input.targetPath,
|
|
5913
|
+
allowRoot: true
|
|
5914
|
+
});
|
|
5915
|
+
await assertExistingPathInsideRealBase({
|
|
5916
|
+
basePath,
|
|
5917
|
+
targetPath
|
|
5918
|
+
});
|
|
5919
|
+
if (!(await stat(targetPath).catch(() => null))?.isDirectory()) throw new ServerPathMutationError("SERVER_PATH_TARGET_NOT_DIRECTORY", "upload target must point to a directory");
|
|
5920
|
+
if (input.files.length === 0) throw new ServerPathMutationError("SERVER_PATH_ENTRY_INVALID", "at least one upload file is required");
|
|
5921
|
+
const normalizedFiles = input.files.map((file) => ({
|
|
5922
|
+
file,
|
|
5923
|
+
name: normalizeEntryName(file.name)
|
|
5924
|
+
}));
|
|
5925
|
+
const uniqueNames = /* @__PURE__ */ new Set();
|
|
5926
|
+
for (const { name } of normalizedFiles) {
|
|
5927
|
+
if (uniqueNames.has(name)) throw new ServerPathMutationError("SERVER_PATH_FILE_NAME_INVALID", "upload file names must be unique");
|
|
5928
|
+
uniqueNames.add(name);
|
|
5929
|
+
}
|
|
5930
|
+
if (!input.overwrite) {
|
|
5931
|
+
const conflicts = (await Promise.all(normalizedFiles.map(async ({ name }) => {
|
|
5932
|
+
return await lstat(join(targetPath, name)).then(() => true).catch(() => false) ? name : null;
|
|
5933
|
+
}))).filter((name) => Boolean(name));
|
|
5934
|
+
if (conflicts.length > 0) throw new ServerPathMutationError("SERVER_PATH_FILE_EXISTS", "one or more upload files already exist", { conflicts });
|
|
5935
|
+
}
|
|
5936
|
+
try {
|
|
5937
|
+
return {
|
|
5938
|
+
files: await Promise.all(normalizedFiles.map(async ({ file, name }) => {
|
|
5939
|
+
const path = resolve(targetPath, name);
|
|
5940
|
+
const content = Buffer.from(await file.arrayBuffer());
|
|
5941
|
+
await writeFile(path, content, { flag: input.overwrite ? "w" : "wx" });
|
|
5942
|
+
return {
|
|
5943
|
+
name,
|
|
5944
|
+
path,
|
|
5945
|
+
sizeBytes: content.byteLength
|
|
5946
|
+
};
|
|
5947
|
+
})),
|
|
5948
|
+
overwritten: input.overwrite
|
|
5949
|
+
};
|
|
5950
|
+
} catch (error) {
|
|
5951
|
+
const code = readFileErrorCode(error);
|
|
5952
|
+
if (code === "EEXIST") throw new ServerPathMutationError("SERVER_PATH_FILE_EXISTS", "one or more upload files already exist");
|
|
5953
|
+
if (code === "ENOENT" || code === "ENOTDIR") throw new ServerPathMutationError("SERVER_PATH_TARGET_NOT_DIRECTORY", "upload target must point to an existing directory");
|
|
5954
|
+
if (code === "EACCES" || code === "EPERM" || code === "EROFS") throw new ServerPathMutationError("SERVER_PATH_TARGET_NOT_WRITABLE", "upload target is not writable");
|
|
5955
|
+
throw error;
|
|
5956
|
+
}
|
|
5957
|
+
}
|
|
5958
|
+
function isServerPathMutationError(error) {
|
|
5959
|
+
return error instanceof ServerPathMutationError;
|
|
5960
|
+
}
|
|
5961
|
+
//#endregion
|
|
5617
5962
|
//#region src/features/server-path/controllers/server-path.controller.ts
|
|
5618
5963
|
function readIncludeFilesFlag(value) {
|
|
5619
5964
|
return value === "1" || value === "true";
|
|
@@ -5661,6 +6006,7 @@ var ServerPathRoutesController = class {
|
|
|
5661
6006
|
if (!body.ok || !isRecord$2(body.data)) return c.json(err("INVALID_SERVER_PATH_DIRECTORY", "directory input is required"), 400);
|
|
5662
6007
|
try {
|
|
5663
6008
|
return c.json(ok(await createServerPathDirectory({
|
|
6009
|
+
basePath: body.data.basePath,
|
|
5664
6010
|
parentPath: body.data.parentPath,
|
|
5665
6011
|
name: body.data.name
|
|
5666
6012
|
})), 201);
|
|
@@ -5669,6 +6015,68 @@ var ServerPathRoutesController = class {
|
|
|
5669
6015
|
throw error;
|
|
5670
6016
|
}
|
|
5671
6017
|
};
|
|
6018
|
+
uploadFiles = async (c) => {
|
|
6019
|
+
let formData;
|
|
6020
|
+
try {
|
|
6021
|
+
formData = await c.req.raw.formData();
|
|
6022
|
+
} catch {
|
|
6023
|
+
return c.json(err("INVALID_SERVER_PATH_UPLOAD", "multipart upload is required"), 400);
|
|
6024
|
+
}
|
|
6025
|
+
const files = formData.getAll("files").flatMap((value) => typeof value === "string" ? [] : [{
|
|
6026
|
+
name: value.name,
|
|
6027
|
+
arrayBuffer: () => value.arrayBuffer()
|
|
6028
|
+
}]);
|
|
6029
|
+
try {
|
|
6030
|
+
return c.json(ok(await uploadServerPathFiles({
|
|
6031
|
+
basePath: formData.get("basePath"),
|
|
6032
|
+
targetPath: formData.get("targetPath"),
|
|
6033
|
+
overwrite: formData.get("overwrite") === "true",
|
|
6034
|
+
files
|
|
6035
|
+
})), 201);
|
|
6036
|
+
} catch (error) {
|
|
6037
|
+
if (isServerPathMutationError(error)) return c.json(err(error.code, error.message, error.details), error.code === "SERVER_PATH_FILE_EXISTS" ? 409 : 400);
|
|
6038
|
+
throw error;
|
|
6039
|
+
}
|
|
6040
|
+
};
|
|
6041
|
+
createFile = async (c) => {
|
|
6042
|
+
const body = await readJson(c.req.raw);
|
|
6043
|
+
if (!body.ok || !isRecord$2(body.data)) return c.json(err("INVALID_SERVER_PATH_FILE", "file input is required"), 400);
|
|
6044
|
+
try {
|
|
6045
|
+
return c.json(ok(await createServerPathFile({
|
|
6046
|
+
basePath: body.data.basePath,
|
|
6047
|
+
parentPath: body.data.parentPath,
|
|
6048
|
+
name: body.data.name
|
|
6049
|
+
})), 201);
|
|
6050
|
+
} catch (error) {
|
|
6051
|
+
if (isServerPathMutationError(error)) return c.json(err(error.code, error.message, error.details), error.code === "SERVER_PATH_FILE_EXISTS" ? 409 : 400);
|
|
6052
|
+
throw error;
|
|
6053
|
+
}
|
|
6054
|
+
};
|
|
6055
|
+
renameEntry = async (c) => {
|
|
6056
|
+
const body = await readJson(c.req.raw);
|
|
6057
|
+
if (!body.ok || !isRecord$2(body.data)) return c.json(err("INVALID_SERVER_PATH_RENAME", "rename input is required"), 400);
|
|
6058
|
+
try {
|
|
6059
|
+
return c.json(ok(await renameServerPathEntry({
|
|
6060
|
+
basePath: body.data.basePath,
|
|
6061
|
+
path: body.data.path,
|
|
6062
|
+
name: body.data.name
|
|
6063
|
+
})));
|
|
6064
|
+
} catch (error) {
|
|
6065
|
+
if (isServerPathMutationError(error)) return c.json(err(error.code, error.message, error.details), error.code === "SERVER_PATH_FILE_EXISTS" ? 409 : 400);
|
|
6066
|
+
throw error;
|
|
6067
|
+
}
|
|
6068
|
+
};
|
|
6069
|
+
deleteEntry = async (c) => {
|
|
6070
|
+
try {
|
|
6071
|
+
return c.json(ok(await deleteServerPathEntry({
|
|
6072
|
+
basePath: c.req.query("basePath"),
|
|
6073
|
+
path: c.req.query("path")
|
|
6074
|
+
})));
|
|
6075
|
+
} catch (error) {
|
|
6076
|
+
if (isServerPathMutationError(error)) return c.json(err(error.code, error.message, error.details), 400);
|
|
6077
|
+
throw error;
|
|
6078
|
+
}
|
|
6079
|
+
};
|
|
5672
6080
|
read = async (c) => {
|
|
5673
6081
|
try {
|
|
5674
6082
|
const payload = await readServerPath({
|
|
@@ -5710,11 +6118,13 @@ function createUiRouteControllers(options, authService, marketplaceBaseUrls) {
|
|
|
5710
6118
|
const { kernel, panelAppClientSdkScript, remoteAccess, runtimeControl, runtimeUpdate } = options;
|
|
5711
6119
|
return {
|
|
5712
6120
|
app: new AppRoutesController(options),
|
|
6121
|
+
appPackages: new AppPackagesRoutesController(kernel.appPackageManager),
|
|
5713
6122
|
agents: new AgentsRoutesController(options),
|
|
5714
6123
|
auth: new AuthRoutesController(authService),
|
|
5715
6124
|
config: new ConfigRoutesController(options),
|
|
5716
6125
|
cron: new CronRoutesController(options),
|
|
5717
6126
|
inboxDeliveries: new InboxDeliveriesRoutesController(kernel.inboxDeliveryManager),
|
|
6127
|
+
systemObjectReferences: new SystemObjectReferencesRoutesController(kernel.systemObjectReferenceManager),
|
|
5718
6128
|
ncpSession: new NcpSessionRoutesController(options),
|
|
5719
6129
|
ncpAsset: new NcpAssetRoutesController(options),
|
|
5720
6130
|
panelApps: new PanelAppsRoutesController(kernel.panelAppManager, { panelAppClientSdkScript }),
|
|
@@ -5833,7 +6243,7 @@ var UiRouteRegistry = class {
|
|
|
5833
6243
|
]]);
|
|
5834
6244
|
};
|
|
5835
6245
|
mountResourceRoutes = () => {
|
|
5836
|
-
const { ncpSession, inboxDeliveries, panelApps, preferences, projects, serviceApps, serverPath } = this.controllers;
|
|
6246
|
+
const { appPackages, ncpSession, inboxDeliveries, panelApps, preferences, projects, serviceApps, serverPath, systemObjectReferences } = this.controllers;
|
|
5837
6247
|
this.mountRoutes([
|
|
5838
6248
|
[
|
|
5839
6249
|
"get",
|
|
@@ -5905,10 +6315,55 @@ var UiRouteRegistry = class {
|
|
|
5905
6315
|
"/api/inbox/deliveries/:deliveryId",
|
|
5906
6316
|
inboxDeliveries.delete
|
|
5907
6317
|
],
|
|
6318
|
+
[
|
|
6319
|
+
"get",
|
|
6320
|
+
"/api/system-object-references",
|
|
6321
|
+
systemObjectReferences.list
|
|
6322
|
+
],
|
|
6323
|
+
[
|
|
6324
|
+
"post",
|
|
6325
|
+
"/api/system-object-references/resolve",
|
|
6326
|
+
systemObjectReferences.resolve
|
|
6327
|
+
],
|
|
6328
|
+
[
|
|
6329
|
+
"get",
|
|
6330
|
+
"/api/app-packages",
|
|
6331
|
+
appPackages.list
|
|
6332
|
+
],
|
|
6333
|
+
[
|
|
6334
|
+
"post",
|
|
6335
|
+
"/api/app-packages/install",
|
|
6336
|
+
appPackages.install
|
|
6337
|
+
],
|
|
6338
|
+
[
|
|
6339
|
+
"get",
|
|
6340
|
+
"/api/app-packages/:appId",
|
|
6341
|
+
appPackages.get
|
|
6342
|
+
],
|
|
6343
|
+
[
|
|
6344
|
+
"post",
|
|
6345
|
+
"/api/app-packages/:appId/enable",
|
|
6346
|
+
appPackages.enable
|
|
6347
|
+
],
|
|
6348
|
+
[
|
|
6349
|
+
"post",
|
|
6350
|
+
"/api/app-packages/:appId/disable",
|
|
6351
|
+
appPackages.disable
|
|
6352
|
+
],
|
|
6353
|
+
[
|
|
6354
|
+
"post",
|
|
6355
|
+
"/api/app-packages/:appId/update",
|
|
6356
|
+
appPackages.update
|
|
6357
|
+
],
|
|
5908
6358
|
[
|
|
5909
6359
|
"post",
|
|
5910
|
-
"/api/
|
|
5911
|
-
|
|
6360
|
+
"/api/app-packages/:appId/rollback",
|
|
6361
|
+
appPackages.rollback
|
|
6362
|
+
],
|
|
6363
|
+
[
|
|
6364
|
+
"delete",
|
|
6365
|
+
"/api/app-packages/:appId",
|
|
6366
|
+
appPackages.uninstall
|
|
5912
6367
|
],
|
|
5913
6368
|
[
|
|
5914
6369
|
"get",
|
|
@@ -6095,6 +6550,26 @@ var UiRouteRegistry = class {
|
|
|
6095
6550
|
"/api/server-paths/directory",
|
|
6096
6551
|
serverPath.createDirectory
|
|
6097
6552
|
],
|
|
6553
|
+
[
|
|
6554
|
+
"post",
|
|
6555
|
+
"/api/server-paths/file",
|
|
6556
|
+
serverPath.createFile
|
|
6557
|
+
],
|
|
6558
|
+
[
|
|
6559
|
+
"post",
|
|
6560
|
+
"/api/server-paths/files",
|
|
6561
|
+
serverPath.uploadFiles
|
|
6562
|
+
],
|
|
6563
|
+
[
|
|
6564
|
+
"patch",
|
|
6565
|
+
"/api/server-paths/entry",
|
|
6566
|
+
serverPath.renameEntry
|
|
6567
|
+
],
|
|
6568
|
+
[
|
|
6569
|
+
"delete",
|
|
6570
|
+
"/api/server-paths/entry",
|
|
6571
|
+
serverPath.deleteEntry
|
|
6572
|
+
],
|
|
6098
6573
|
[
|
|
6099
6574
|
"get",
|
|
6100
6575
|
"/api/server-paths/read",
|
|
@@ -6670,6 +7145,6 @@ async function startUiServer(gateway) {
|
|
|
6670
7145
|
};
|
|
6671
7146
|
}
|
|
6672
7147
|
//#endregion
|
|
6673
|
-
export { ConfigRoutesController, InboxDeliveriesRoutesController, PanelAppsRoutesController, RuntimeControlRoutesController, ServiceAppsRoutesController, buildConfigMeta, buildConfigSchemaView, buildConfigView, buildProviderTemplatesView, buildProvidersView, createProvider, createUiRouter, deleteProvider, ensureUiBridgeSecret, executeConfigAction, getUiBridgeSecretPath, loadConfigOrDefault, readUiBridgeSecret, startUiServer, updateChannel, updateModel, updateProvider, updateRuntime, updateSearch, updateSecrets };
|
|
7148
|
+
export { AppPackagesRoutesController, ConfigRoutesController, InboxDeliveriesRoutesController, PanelAppsRoutesController, RuntimeControlRoutesController, ServiceAppsRoutesController, buildConfigMeta, buildConfigSchemaView, buildConfigView, buildProviderTemplatesView, buildProvidersView, createProvider, createUiRouter, deleteProvider, ensureUiBridgeSecret, executeConfigAction, getUiBridgeSecretPath, loadConfigOrDefault, readUiBridgeSecret, startUiServer, updateChannel, updateModel, updateProvider, updateRuntime, updateSearch, updateSecrets };
|
|
6674
7149
|
|
|
6675
7150
|
//# sourceMappingURL=index.js.map
|