@nextclaw/server 0.18.2 → 0.19.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/dist/index.d.ts +28 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +294 -14
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -8,10 +8,10 @@ import { lstat, mkdir, open, readFile, readdir, realpath, rename, rm, stat, writ
|
|
|
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";
|
|
11
|
-
import { ConfigSchema, DEFAULT_WORKSPACE_PATH, ProviderModelDiscoveryHttpError, buildConfigSchema, createAgentProfile, expandHome, findEffectiveAgentProfile, getDataDir, getPackageVersion, getProviderName, hasSecretRef, isSensitiveConfigPath, loadConfig, mergeExtensionConfigView, normalizeModelThinkingCapability, normalizeProviderModelConfig, probeFeishu, readAgentAvatarContent, removeAgentProfile, resolveEffectiveAgentProfiles, saveConfig, toExtensionConfigView, updateAgentProfile } from "@nextclaw/core";
|
|
11
|
+
import { ConfigSchema, DEFAULT_WORKSPACE_PATH, McpServerDefinitionSchema, ProviderModelDiscoveryHttpError, buildConfigSchema, createAgentProfile, expandHome, findEffectiveAgentProfile, getDataDir, getPackageVersion, getProviderName, hasSecretRef, isSensitiveConfigPath, loadConfig, mergeExtensionConfigView, normalizeModelThinkingCapability, normalizeProviderModelConfig, probeFeishu, readAgentAvatarContent, removeAgentProfile, resolveEffectiveAgentProfiles, saveConfig, toExtensionConfigView, updateAgentProfile } from "@nextclaw/core";
|
|
12
12
|
import { homedir, platform } from "node:os";
|
|
13
13
|
import { findBuiltinProviderByName, listBuiltinProviders } from "@nextclaw/runtime";
|
|
14
|
-
import { McpInstalledViewService } from "@nextclaw/mcp";
|
|
14
|
+
import { McpInstalledViewService, McpMutationService, McpRegistryService, normalizeMcpServerName } from "@nextclaw/mcp";
|
|
15
15
|
import { serveStatic } from "hono/serve-static";
|
|
16
16
|
//#region src/features/auth/utils/auth-bridge.utils.ts
|
|
17
17
|
const REMOTE_BRIDGE_DIR = join(getDataDir(), "remote");
|
|
@@ -67,7 +67,7 @@ async function readJson(req) {
|
|
|
67
67
|
function isRecord$3(value) {
|
|
68
68
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
69
69
|
}
|
|
70
|
-
function readErrorMessage(value, fallback) {
|
|
70
|
+
function readErrorMessage$1(value, fallback) {
|
|
71
71
|
if (!isRecord$3(value)) return fallback;
|
|
72
72
|
const maybeError = value.error;
|
|
73
73
|
if (!isRecord$3(maybeError)) return fallback;
|
|
@@ -390,7 +390,7 @@ function readNcpEventChannel(event) {
|
|
|
390
390
|
return readString(metadata.channelId) ?? readString(metadata.channel) ?? parseAgentSessionChannel(readString(message.sessionId) ?? readString(payload.sessionId));
|
|
391
391
|
}
|
|
392
392
|
function canStreamAppEventToPrincipal(principal, event) {
|
|
393
|
-
if (event.type === "extension.request") {
|
|
393
|
+
if (event.type === "extension.request" || event.type === "extension.host.desktop.event") {
|
|
394
394
|
const target = readExtensionRequestTarget(event);
|
|
395
395
|
return hasGrant(principal, "event-stream:extension-requests") && hasScopeValue(principal, "extensionIds", target.extensionId) && hasScopeValue(principal, "extensionGenerations", target.extensionId && target.generation ? `${target.extensionId}:${target.generation}` : null);
|
|
396
396
|
}
|
|
@@ -478,7 +478,8 @@ const ingressKeys = {
|
|
|
478
478
|
channelCommandExecute: createTypedKey("extension.channel.command.execute"),
|
|
479
479
|
runtimeReady: createTypedKey("extension.runtime.ready"),
|
|
480
480
|
response: createTypedKey("extension.response"),
|
|
481
|
-
observationEvent: createTypedKey("extension.observation.event")
|
|
481
|
+
observationEvent: createTypedKey("extension.observation.event"),
|
|
482
|
+
desktopHostInvoke: createTypedKey("extension.host.desktop.invoke")
|
|
482
483
|
},
|
|
483
484
|
agentRun: {
|
|
484
485
|
send: createTypedKey("agent-run.send"),
|
|
@@ -1964,6 +1965,131 @@ var AppRoutesController = class {
|
|
|
1964
1965
|
extensionCatalog = (c) => c.json(ok(buildExtensionsView(this.options)));
|
|
1965
1966
|
};
|
|
1966
1967
|
//#endregion
|
|
1968
|
+
//#region src/app/controllers/capability-access.controller.ts
|
|
1969
|
+
var CapabilityAccessRoutesController = class {
|
|
1970
|
+
constructor(options) {
|
|
1971
|
+
this.options = options;
|
|
1972
|
+
}
|
|
1973
|
+
listGrants = async (c) => this.listDesktopGrants(c);
|
|
1974
|
+
grant = async (c) => {
|
|
1975
|
+
const body = await readJson(c.req.raw);
|
|
1976
|
+
const request = body.ok ? readGrantRequest(body.data) : null;
|
|
1977
|
+
if (!request) return c.json(err("INVALID_CAPABILITY_GRANT", "A valid capability grant request is required."), 400);
|
|
1978
|
+
try {
|
|
1979
|
+
if (request.resource.type !== "desktop.application") return c.json(err("INVALID_CAPABILITY_GRANT", "Generic capability grants must use their resource-specific authorization endpoint."), 400);
|
|
1980
|
+
return c.json(ok(await this.options.getDesktopHost().grantAccess(request)), 201);
|
|
1981
|
+
} catch (error) {
|
|
1982
|
+
return c.json(err("INVALID_CAPABILITY_GRANT", readErrorMessage(error)), 400);
|
|
1983
|
+
}
|
|
1984
|
+
};
|
|
1985
|
+
revoke = async (c) => {
|
|
1986
|
+
const body = await readJson(c.req.raw);
|
|
1987
|
+
const filter = body.ok ? readGrantFilter(body.data) : null;
|
|
1988
|
+
if (!filter || !isExactGrantSelector(filter) || filter.resourceType !== "desktop.application") return c.json(err("INVALID_CAPABILITY_GRANT_FILTER", "An exact Desktop subject, resource type, and target selector is required."), 400);
|
|
1989
|
+
return c.json(ok({ revoked: await this.options.capabilityGrantManager.revoke(filter) }));
|
|
1990
|
+
};
|
|
1991
|
+
getDesktopStatus = async (c) => c.json(ok(await this.options.getDesktopHost().status()));
|
|
1992
|
+
getDesktopPermissions = async (c) => c.json(ok(await this.options.getDesktopHost().getPermissions()));
|
|
1993
|
+
requestDesktopPermissions = async (c) => c.json(ok(await this.options.getDesktopHost().requestPermissions()));
|
|
1994
|
+
openDesktopPermissionSettings = async (c) => c.json(ok(await this.options.getDesktopHost().openPermissionSettings()));
|
|
1995
|
+
listDesktopGrants = async (c) => {
|
|
1996
|
+
const filter = readGrantFilterFromQuery(c);
|
|
1997
|
+
if (filter.resourceType !== void 0 && filter.resourceType !== "desktop.application") return c.json(err("INVALID_CAPABILITY_GRANT_FILTER", "Only Desktop capability grants can be listed from this endpoint."), 400);
|
|
1998
|
+
if (filter.subject && (!filter.subject.type || !filter.subject.id)) return c.json(err("INVALID_CAPABILITY_GRANT_FILTER", "Desktop grant subject filters must include both type and id."), 400);
|
|
1999
|
+
return c.json(ok(await this.options.capabilityGrantManager.list({
|
|
2000
|
+
...filter,
|
|
2001
|
+
resourceType: "desktop.application"
|
|
2002
|
+
})));
|
|
2003
|
+
};
|
|
2004
|
+
};
|
|
2005
|
+
function isExactGrantSelector(filter) {
|
|
2006
|
+
return Boolean(filter.subject?.type && filter.subject.id && filter.resourceType && filter.access?.length && Object.hasOwn(filter, "target") && filter.target !== void 0);
|
|
2007
|
+
}
|
|
2008
|
+
function readGrantFilterFromQuery(c) {
|
|
2009
|
+
const subjectType = readOptionalString(c.req.query("subjectType"));
|
|
2010
|
+
const subjectId = readOptionalString(c.req.query("subjectId"));
|
|
2011
|
+
const resourceType = readOptionalString(c.req.query("resourceType"));
|
|
2012
|
+
return {
|
|
2013
|
+
...subjectType || subjectId ? { subject: {
|
|
2014
|
+
...subjectType ? { type: subjectType } : {},
|
|
2015
|
+
...subjectId ? { id: subjectId } : {}
|
|
2016
|
+
} } : {},
|
|
2017
|
+
...resourceType ? { resourceType } : {}
|
|
2018
|
+
};
|
|
2019
|
+
}
|
|
2020
|
+
function readGrantRequest(value) {
|
|
2021
|
+
if (!isRecord$3(value) || !hasExactKeys(value, [
|
|
2022
|
+
"access",
|
|
2023
|
+
"declarationFingerprint",
|
|
2024
|
+
"resource",
|
|
2025
|
+
"subject"
|
|
2026
|
+
])) return null;
|
|
2027
|
+
const subject = readSubject(value.subject, false);
|
|
2028
|
+
const resource = isRecord$3(value.resource) && hasExactKeys(value.resource, ["target", "type"]) ? value.resource : null;
|
|
2029
|
+
if (!subject || !resource || !readOptionalString(resource.type) || !Array.isArray(value.access) || value.access.length === 0 || !value.access.every((entry) => Boolean(readOptionalString(entry))) || !readOptionalString(value.declarationFingerprint)) return null;
|
|
2030
|
+
return {
|
|
2031
|
+
subject: {
|
|
2032
|
+
type: subject.type,
|
|
2033
|
+
id: subject.id
|
|
2034
|
+
},
|
|
2035
|
+
resource: {
|
|
2036
|
+
type: String(resource.type).trim(),
|
|
2037
|
+
target: resource.target
|
|
2038
|
+
},
|
|
2039
|
+
access: value.access.map((entry) => String(entry).trim()),
|
|
2040
|
+
declarationFingerprint: String(value.declarationFingerprint).trim()
|
|
2041
|
+
};
|
|
2042
|
+
}
|
|
2043
|
+
function readGrantFilter(value) {
|
|
2044
|
+
if (!isRecord$3(value) || !hasExactKeys(value, [
|
|
2045
|
+
"access",
|
|
2046
|
+
"resourceType",
|
|
2047
|
+
"subject",
|
|
2048
|
+
"target"
|
|
2049
|
+
], true)) return null;
|
|
2050
|
+
const subject = value.subject === void 0 ? void 0 : readSubject(value.subject, true);
|
|
2051
|
+
if (value.subject !== void 0 && !subject) return null;
|
|
2052
|
+
const resourceType = value.resourceType === void 0 ? void 0 : readOptionalString(value.resourceType);
|
|
2053
|
+
if (value.resourceType !== void 0 && !resourceType) return null;
|
|
2054
|
+
const access = value.access === void 0 ? void 0 : Array.isArray(value.access) && value.access.length > 0 && value.access.every((entry) => Boolean(readOptionalString(entry))) ? value.access.map((entry) => String(entry).trim()) : null;
|
|
2055
|
+
if (access === null) return null;
|
|
2056
|
+
return {
|
|
2057
|
+
...subject ? { subject } : {},
|
|
2058
|
+
...resourceType ? { resourceType } : {},
|
|
2059
|
+
...Object.hasOwn(value, "target") ? { target: value.target } : {},
|
|
2060
|
+
...access ? { access } : {}
|
|
2061
|
+
};
|
|
2062
|
+
}
|
|
2063
|
+
function readSubject(value, partial) {
|
|
2064
|
+
if (!isRecord$3(value) || !hasExactKeys(value, ["id", "type"], partial)) return null;
|
|
2065
|
+
const type = value.type === void 0 ? void 0 : readOptionalString(value.type);
|
|
2066
|
+
const id = value.id === void 0 ? void 0 : readOptionalString(value.id);
|
|
2067
|
+
if (!partial && (!type || !id) || value.type !== void 0 && !type || value.id !== void 0 && !id) return null;
|
|
2068
|
+
return {
|
|
2069
|
+
...type ? { type } : {},
|
|
2070
|
+
...id ? { id } : {}
|
|
2071
|
+
};
|
|
2072
|
+
}
|
|
2073
|
+
function hasExactKeys(value, allowed, allowMissing = false) {
|
|
2074
|
+
const keys = Object.keys(value);
|
|
2075
|
+
return keys.every((key) => allowed.includes(key)) && (allowMissing || keys.length === allowed.length);
|
|
2076
|
+
}
|
|
2077
|
+
function readOptionalString(value) {
|
|
2078
|
+
if (typeof value !== "string") return void 0;
|
|
2079
|
+
return value.trim() || void 0;
|
|
2080
|
+
}
|
|
2081
|
+
function readErrorMessage(error) {
|
|
2082
|
+
return error instanceof Error ? error.message : String(error);
|
|
2083
|
+
}
|
|
2084
|
+
//#endregion
|
|
2085
|
+
//#region src/features/feature-controls/controllers/feature-controls.controller.ts
|
|
2086
|
+
var FeatureControlsRoutesController = class {
|
|
2087
|
+
constructor(featureControls) {
|
|
2088
|
+
this.featureControls = featureControls;
|
|
2089
|
+
}
|
|
2090
|
+
get = async (c) => c.json(ok(await this.featureControls.get()));
|
|
2091
|
+
};
|
|
2092
|
+
//#endregion
|
|
1967
2093
|
//#region src/features/app-packages/controllers/app-packages.controller.ts
|
|
1968
2094
|
var AppPackagesRoutesController = class {
|
|
1969
2095
|
constructor(manager) {
|
|
@@ -4846,7 +4972,7 @@ async function fetchMarketplaceDataFromBase(params) {
|
|
|
4846
4972
|
if (!response.ok) return {
|
|
4847
4973
|
ok: false,
|
|
4848
4974
|
status: response.status,
|
|
4849
|
-
message: readErrorMessage(payload, `marketplace request failed (${response.status})`)
|
|
4975
|
+
message: readErrorMessage$1(payload, `marketplace request failed (${response.status})`)
|
|
4850
4976
|
};
|
|
4851
4977
|
if (!payload || typeof payload !== "object" || !("ok" in payload)) return {
|
|
4852
4978
|
ok: false,
|
|
@@ -4857,7 +4983,7 @@ async function fetchMarketplaceDataFromBase(params) {
|
|
|
4857
4983
|
if (!typed.ok) return {
|
|
4858
4984
|
ok: false,
|
|
4859
4985
|
status: 502,
|
|
4860
|
-
message: readErrorMessage(payload, "marketplace response returned error")
|
|
4986
|
+
message: readErrorMessage$1(payload, "marketplace response returned error")
|
|
4861
4987
|
};
|
|
4862
4988
|
return {
|
|
4863
4989
|
ok: true,
|
|
@@ -5740,6 +5866,8 @@ function buildSessionObservationsView(input) {
|
|
|
5740
5866
|
//#region src/features/sessions/controllers/sessions.controller.ts
|
|
5741
5867
|
const DEFAULT_SESSION_MESSAGE_PAGE_SIZE = 40;
|
|
5742
5868
|
const MAX_SESSION_MESSAGE_PAGE_SIZE = 200;
|
|
5869
|
+
const DEFAULT_SESSION_LIST_PAGE_SIZE = 100;
|
|
5870
|
+
const MAX_SESSION_LIST_PAGE_SIZE = 200;
|
|
5743
5871
|
function sessionProjectError(error) {
|
|
5744
5872
|
switch (error.code) {
|
|
5745
5873
|
case "PROJECT_PATH_INVALID_TYPE": return {
|
|
@@ -5806,13 +5934,36 @@ var NcpSessionRoutesController = class {
|
|
|
5806
5934
|
return c.json(ok(payload));
|
|
5807
5935
|
};
|
|
5808
5936
|
listSessions = async (c) => {
|
|
5809
|
-
const
|
|
5810
|
-
|
|
5811
|
-
|
|
5937
|
+
const sessionManager = this.options.kernel.sessionManager;
|
|
5938
|
+
const page = readPositiveInt(c.req.query("page")) ?? 1;
|
|
5939
|
+
const pageSize = Math.min(readPositiveInt(c.req.query("pageSize")) ?? readPositiveInt(c.req.query("limit")) ?? DEFAULT_SESSION_LIST_PAGE_SIZE, MAX_SESSION_LIST_PAGE_SIZE);
|
|
5940
|
+
const rawQuery = c.req.query("query")?.trim();
|
|
5941
|
+
const peerId = c.req.query("peerId")?.trim();
|
|
5942
|
+
if (peerId) {
|
|
5943
|
+
const sessions = await sessionManager.listSessions({
|
|
5944
|
+
limit: pageSize,
|
|
5945
|
+
peerId
|
|
5946
|
+
});
|
|
5947
|
+
const payload = {
|
|
5948
|
+
sessions: sessions.map(this.withRuntimeStatus),
|
|
5949
|
+
total: sessions.length,
|
|
5950
|
+
page: 1,
|
|
5951
|
+
pageSize,
|
|
5952
|
+
hasMore: false
|
|
5953
|
+
};
|
|
5954
|
+
return c.json(ok(payload));
|
|
5955
|
+
}
|
|
5956
|
+
const result = await sessionManager.listSessionPage({
|
|
5957
|
+
page,
|
|
5958
|
+
pageSize,
|
|
5959
|
+
...rawQuery ? { query: rawQuery } : {}
|
|
5812
5960
|
});
|
|
5813
5961
|
const payload = {
|
|
5814
|
-
sessions: sessions.map(this.withRuntimeStatus),
|
|
5815
|
-
total:
|
|
5962
|
+
sessions: result.sessions.map(this.withRuntimeStatus),
|
|
5963
|
+
total: result.total,
|
|
5964
|
+
page,
|
|
5965
|
+
pageSize,
|
|
5966
|
+
hasMore: page * pageSize < result.total
|
|
5816
5967
|
};
|
|
5817
5968
|
return c.json(ok(payload));
|
|
5818
5969
|
};
|
|
@@ -6013,6 +6164,88 @@ var NcpSessionRoutesController = class {
|
|
|
6013
6164
|
};
|
|
6014
6165
|
};
|
|
6015
6166
|
//#endregion
|
|
6167
|
+
//#region src/features/mcp/controllers/mcp.controller.ts
|
|
6168
|
+
var McpRoutesController = class {
|
|
6169
|
+
constructor(options) {
|
|
6170
|
+
this.options = options;
|
|
6171
|
+
}
|
|
6172
|
+
testConnection = async (c) => {
|
|
6173
|
+
const parsed = await this.readConnectionRequest(c);
|
|
6174
|
+
if (!parsed.ok) return parsed.response;
|
|
6175
|
+
const config = structuredClone(loadConfig(this.options.configPath));
|
|
6176
|
+
const result = new McpMutationService({
|
|
6177
|
+
getConfig: () => config,
|
|
6178
|
+
saveConfig: () => void 0
|
|
6179
|
+
}).addServer(parsed.value.name, parsed.value.definition);
|
|
6180
|
+
if (!result.changed) return c.json(err("MCP_CONNECTION_INVALID", result.message), 400);
|
|
6181
|
+
const registry = new McpRegistryService({ getConfig: () => config });
|
|
6182
|
+
try {
|
|
6183
|
+
const warm = await registry.warmServer(result.name);
|
|
6184
|
+
return c.json(ok({
|
|
6185
|
+
name: warm.name,
|
|
6186
|
+
transport: parsed.value.definition.transport.type,
|
|
6187
|
+
accessible: warm.ok,
|
|
6188
|
+
toolCount: warm.toolCount,
|
|
6189
|
+
...warm.error ? { error: warm.error } : {}
|
|
6190
|
+
}));
|
|
6191
|
+
} finally {
|
|
6192
|
+
await registry.close();
|
|
6193
|
+
}
|
|
6194
|
+
};
|
|
6195
|
+
createConnection = async (c) => {
|
|
6196
|
+
const parsed = await this.readConnectionRequest(c);
|
|
6197
|
+
if (!parsed.ok) return parsed.response;
|
|
6198
|
+
const result = new McpMutationService({
|
|
6199
|
+
getConfig: () => loadConfig(this.options.configPath),
|
|
6200
|
+
saveConfig: (config) => saveConfig(config, this.options.configPath)
|
|
6201
|
+
}).addServer(parsed.value.name, parsed.value.definition);
|
|
6202
|
+
if (!result.changed || !result.definition) return c.json(err("MCP_CONNECTION_INVALID", result.message), 400);
|
|
6203
|
+
emitConfigUpdated(this.options, "mcp");
|
|
6204
|
+
await this.options.applyLiveConfigReload?.();
|
|
6205
|
+
return c.json(ok({
|
|
6206
|
+
name: result.name,
|
|
6207
|
+
transport: result.definition.transport.type,
|
|
6208
|
+
message: result.message
|
|
6209
|
+
}));
|
|
6210
|
+
};
|
|
6211
|
+
readConnectionRequest = async (c) => {
|
|
6212
|
+
const body = await readJson(c.req.raw);
|
|
6213
|
+
if (!body.ok || !body.data || typeof body.data !== "object") return {
|
|
6214
|
+
ok: false,
|
|
6215
|
+
response: c.json(err("INVALID_BODY", "invalid json body"), 400)
|
|
6216
|
+
};
|
|
6217
|
+
try {
|
|
6218
|
+
const name = normalizeMcpServerName(body.data.name ?? "");
|
|
6219
|
+
const definition = McpServerDefinitionSchema.parse(body.data.definition);
|
|
6220
|
+
return {
|
|
6221
|
+
ok: true,
|
|
6222
|
+
value: {
|
|
6223
|
+
name,
|
|
6224
|
+
definition: {
|
|
6225
|
+
...definition,
|
|
6226
|
+
metadata: {
|
|
6227
|
+
...definition.metadata,
|
|
6228
|
+
source: "manual",
|
|
6229
|
+
installedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
6230
|
+
}
|
|
6231
|
+
}
|
|
6232
|
+
}
|
|
6233
|
+
};
|
|
6234
|
+
} catch (error) {
|
|
6235
|
+
return {
|
|
6236
|
+
ok: false,
|
|
6237
|
+
response: c.json(err("MCP_CONNECTION_INVALID", error instanceof Error ? error.message : String(error)), 400)
|
|
6238
|
+
};
|
|
6239
|
+
}
|
|
6240
|
+
};
|
|
6241
|
+
};
|
|
6242
|
+
//#endregion
|
|
6243
|
+
//#region src/features/mcp/routes/mcp.route.ts
|
|
6244
|
+
function mountMcpRoutes(app, controller) {
|
|
6245
|
+
app.post("/api/mcp/servers/test", controller.testConnection);
|
|
6246
|
+
app.post("/api/mcp/servers", controller.createConnection);
|
|
6247
|
+
}
|
|
6248
|
+
//#endregion
|
|
6016
6249
|
//#region src/features/remote-access/controllers/remote.controller.ts
|
|
6017
6250
|
const REMOTE_SERVICE_ACTIONS = new Set([
|
|
6018
6251
|
"start",
|
|
@@ -6723,6 +6956,11 @@ function createUiRouteControllers(options, authService, marketplaceBaseUrls, ser
|
|
|
6723
6956
|
const { kernel, panelAppClientSdkScript, remoteAccess, runtimeControl, runtimeUpdate } = options;
|
|
6724
6957
|
return {
|
|
6725
6958
|
app: new AppRoutesController(options),
|
|
6959
|
+
capabilityAccess: new CapabilityAccessRoutesController({
|
|
6960
|
+
capabilityGrantManager: kernel.capabilityGrants,
|
|
6961
|
+
getDesktopHost: () => kernel.extensions.getDesktopHost()
|
|
6962
|
+
}),
|
|
6963
|
+
featureControls: new FeatureControlsRoutesController(kernel.featureControls),
|
|
6726
6964
|
appPackages: new AppPackagesRoutesController(kernel.appPackageManager),
|
|
6727
6965
|
appData: new AppDataRoutesController(kernel.appDataManager),
|
|
6728
6966
|
agents: new AgentsRoutesController(options),
|
|
@@ -6745,7 +6983,8 @@ function createUiRouteControllers(options, authService, marketplaceBaseUrls, ser
|
|
|
6745
6983
|
runtimeControl: runtimeControl ? new RuntimeControlRoutesController(runtimeControl) : null,
|
|
6746
6984
|
runtimeUpdate: runtimeUpdate ? new RuntimeUpdateRoutesController(runtimeUpdate) : null,
|
|
6747
6985
|
skillMarketplace: new SkillMarketplaceController(options, marketplaceBaseUrls),
|
|
6748
|
-
mcpMarketplace: new McpMarketplaceController(options, marketplaceBaseUrls)
|
|
6986
|
+
mcpMarketplace: new McpMarketplaceController(options, marketplaceBaseUrls),
|
|
6987
|
+
mcp: new McpRoutesController(options)
|
|
6749
6988
|
};
|
|
6750
6989
|
}
|
|
6751
6990
|
function isRecord(value) {
|
|
@@ -6849,7 +7088,7 @@ var UiRouteRegistry = class {
|
|
|
6849
7088
|
]]);
|
|
6850
7089
|
};
|
|
6851
7090
|
mountResourceRoutes = () => {
|
|
6852
|
-
const { appData, appPackages, ncpSession, inboxDeliveries, panelApps, preferences, projects, serviceApps, serverPath, systemObjectReferences } = this.controllers;
|
|
7091
|
+
const { appData, appPackages, capabilityAccess, featureControls, ncpSession, inboxDeliveries, panelApps, preferences, projects, serviceApps, serverPath, systemObjectReferences } = this.controllers;
|
|
6853
7092
|
this.mountRoutes([
|
|
6854
7093
|
[
|
|
6855
7094
|
"get",
|
|
@@ -6956,6 +7195,46 @@ var UiRouteRegistry = class {
|
|
|
6956
7195
|
"/api/system-object-references/resolve",
|
|
6957
7196
|
systemObjectReferences.resolve
|
|
6958
7197
|
],
|
|
7198
|
+
[
|
|
7199
|
+
"get",
|
|
7200
|
+
"/api/capability-grants",
|
|
7201
|
+
capabilityAccess.listGrants
|
|
7202
|
+
],
|
|
7203
|
+
[
|
|
7204
|
+
"post",
|
|
7205
|
+
"/api/capability-grants",
|
|
7206
|
+
capabilityAccess.grant
|
|
7207
|
+
],
|
|
7208
|
+
[
|
|
7209
|
+
"delete",
|
|
7210
|
+
"/api/capability-grants",
|
|
7211
|
+
capabilityAccess.revoke
|
|
7212
|
+
],
|
|
7213
|
+
[
|
|
7214
|
+
"get",
|
|
7215
|
+
"/api/feature-controls",
|
|
7216
|
+
featureControls.get
|
|
7217
|
+
],
|
|
7218
|
+
[
|
|
7219
|
+
"get",
|
|
7220
|
+
"/api/desktop-host/status",
|
|
7221
|
+
capabilityAccess.getDesktopStatus
|
|
7222
|
+
],
|
|
7223
|
+
[
|
|
7224
|
+
"get",
|
|
7225
|
+
"/api/desktop-host/permissions",
|
|
7226
|
+
capabilityAccess.getDesktopPermissions
|
|
7227
|
+
],
|
|
7228
|
+
[
|
|
7229
|
+
"post",
|
|
7230
|
+
"/api/desktop-host/permissions/request",
|
|
7231
|
+
capabilityAccess.requestDesktopPermissions
|
|
7232
|
+
],
|
|
7233
|
+
[
|
|
7234
|
+
"post",
|
|
7235
|
+
"/api/desktop-host/permissions/open-settings",
|
|
7236
|
+
capabilityAccess.openDesktopPermissionSettings
|
|
7237
|
+
],
|
|
6959
7238
|
[
|
|
6960
7239
|
"get",
|
|
6961
7240
|
"/api/app-packages",
|
|
@@ -7625,6 +7904,7 @@ var UiRouteRegistry = class {
|
|
|
7625
7904
|
skill: this.controllers.skillMarketplace,
|
|
7626
7905
|
mcp: this.controllers.mcpMarketplace
|
|
7627
7906
|
});
|
|
7907
|
+
mountMcpRoutes(this.app, this.controllers.mcp);
|
|
7628
7908
|
};
|
|
7629
7909
|
};
|
|
7630
7910
|
function createUiRouter(options, authServiceOverride, internal) {
|