@nextclaw/server 0.13.4 → 0.13.5

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.js CHANGED
@@ -832,23 +832,6 @@ async function connectChannelAuth(params) {
832
832
  return toPublicChannelAuthPollResult(result);
833
833
  }
834
834
  //#endregion
835
- //#region src/features/config/utils/default-provider-config.utils.ts
836
- function createDefaultProviderConfig(defaultWireApi = "auto", defaultModels = [], modelConfig = {}) {
837
- return {
838
- enabled: true,
839
- displayName: "",
840
- apiKey: "",
841
- apiBase: null,
842
- extraHeaders: null,
843
- wireApi: defaultWireApi,
844
- models: [...defaultModels],
845
- modelConfig
846
- };
847
- }
848
- function createDefaultProviderConfigFromSpec(spec) {
849
- return createDefaultProviderConfig(spec?.defaultWireApi ?? "auto", spec?.defaultModels ?? [], normalizeProviderModelConfig(spec?.modelConfig ?? {}));
850
- }
851
- //#endregion
852
835
  //#region src/features/config/providers/server-builtin-provider.provider.ts
853
836
  const SERVER_BUILTIN_PROVIDER_OVERRIDES = [{
854
837
  name: "minimax-portal",
@@ -864,7 +847,12 @@ const SERVER_BUILTIN_PROVIDER_OVERRIDES = [{
864
847
  detectByKeyPrefix: "",
865
848
  detectByBaseKeyword: "",
866
849
  defaultApiBase: "https://api.minimax.io/v1",
867
- defaultModels: ["minimax-portal/MiniMax-M2.5", "minimax-portal/MiniMax-M2.5-highspeed"],
850
+ defaultModels: [
851
+ "minimax-portal/MiniMax-M3",
852
+ "minimax-portal/MiniMax-M2.5",
853
+ "minimax-portal/MiniMax-M2.5-highspeed"
854
+ ],
855
+ modelConfig: { "minimax-portal/MiniMax-M3": { vision: true } },
868
856
  stripModelPrefix: false,
869
857
  modelOverrides: [],
870
858
  logo: "minimax.svg",
@@ -1068,15 +1056,33 @@ function readFieldAsString(source, fieldName) {
1068
1056
  function setProviderApiKey({ configPath, provider, accessToken, defaultApiBase }) {
1069
1057
  const config = loadConfig(configPath);
1070
1058
  const providers = config.providers;
1071
- if (!providers[provider]) providers[provider] = createDefaultProviderConfigFromSpec(findServerBuiltinProviderByName(provider));
1059
+ if (!providers[provider]) return;
1072
1060
  const target = providers[provider];
1073
1061
  target.apiKey = accessToken;
1074
- if (!target.apiBase && defaultApiBase) target.apiBase = defaultApiBase;
1062
+ if (defaultApiBase) target.apiBase = defaultApiBase;
1075
1063
  saveConfig(ConfigSchema.parse(config), configPath);
1076
1064
  }
1077
- async function startProviderAuth(configPath, providerName, options) {
1065
+ function resolveProviderAuthTarget(configPath, providerId) {
1066
+ const provider = loadConfig(configPath).providers[providerId];
1067
+ if (!provider) return null;
1068
+ const configuredType = typeof provider.providerType === "string" ? provider.providerType.trim() : "";
1069
+ if (configuredType && findServerBuiltinProviderByName(configuredType)) return {
1070
+ providerId,
1071
+ providerType: configuredType,
1072
+ provider
1073
+ };
1074
+ if (findServerBuiltinProviderByName(providerId)) return {
1075
+ providerId,
1076
+ providerType: providerId,
1077
+ provider
1078
+ };
1079
+ return null;
1080
+ }
1081
+ async function startProviderAuth(configPath, providerId, options) {
1078
1082
  cleanupExpiredAuthSessions();
1079
- const spec = findServerBuiltinProviderByName(providerName);
1083
+ const target = resolveProviderAuthTarget(configPath, providerId);
1084
+ if (!target) return null;
1085
+ const spec = findServerBuiltinProviderByName(target.providerType);
1080
1086
  if (!spec?.auth || spec.auth.kind !== "device_code") return null;
1081
1087
  const resolvedMethod = resolveAuthMethod(spec.auth, options?.methodId);
1082
1088
  const { deviceCodeEndpoint, tokenEndpoint } = resolveDeviceCodeEndpoints(resolvedMethod.baseUrl, resolvedMethod.deviceCodePath, resolvedMethod.tokenPath);
@@ -1150,7 +1156,8 @@ async function startProviderAuth(configPath, providerName, options) {
1150
1156
  const sessionId = randomUUID();
1151
1157
  authSessions.set(sessionId, {
1152
1158
  sessionId,
1153
- provider: providerName,
1159
+ providerId,
1160
+ providerType: target.providerType,
1154
1161
  configPath,
1155
1162
  authorizationCode,
1156
1163
  tokenCodeField,
@@ -1168,7 +1175,7 @@ async function startProviderAuth(configPath, providerName, options) {
1168
1175
  const methodLabel = methodConfig ? resolveLocalizedMethodLabel(methodConfig, resolvedMethod.id ?? "") : void 0;
1169
1176
  const methodHint = methodConfig ? resolveLocalizedMethodHint(methodConfig) : void 0;
1170
1177
  return {
1171
- provider: providerName,
1178
+ provider: providerId,
1172
1179
  kind: "device_code",
1173
1180
  methodId: resolvedMethod.id,
1174
1181
  sessionId,
@@ -1180,14 +1187,14 @@ async function startProviderAuth(configPath, providerName, options) {
1180
1187
  };
1181
1188
  }
1182
1189
  async function pollProviderAuth(params) {
1183
- const { configPath, providerName, sessionId } = params;
1190
+ const { configPath, providerName: providerId, sessionId } = params;
1184
1191
  cleanupExpiredAuthSessions();
1185
1192
  const session = authSessions.get(sessionId);
1186
- if (!session || session.provider !== providerName || session.configPath !== configPath) return null;
1193
+ if (!session || session.providerId !== providerId || session.configPath !== configPath) return null;
1187
1194
  if (Date.now() >= session.expiresAtMs) {
1188
1195
  authSessions.delete(sessionId);
1189
1196
  return {
1190
- provider: providerName,
1197
+ provider: providerId,
1191
1198
  status: "expired",
1192
1199
  message: "authorization session expired"
1193
1200
  };
@@ -1216,7 +1223,7 @@ async function pollProviderAuth(params) {
1216
1223
  payload = {};
1217
1224
  }
1218
1225
  if (!response.ok) return {
1219
- provider: providerName,
1226
+ provider: providerId,
1220
1227
  status: "error",
1221
1228
  message: buildMinimaxErrorMessage(payload, raw || response.statusText || "authorization failed")
1222
1229
  };
@@ -1224,7 +1231,7 @@ async function pollProviderAuth(params) {
1224
1231
  if (status === "success") {
1225
1232
  accessToken = payload.access_token?.trim() ?? "";
1226
1233
  if (!accessToken) return {
1227
- provider: providerName,
1234
+ provider: providerId,
1228
1235
  status: "error",
1229
1236
  message: "provider token response missing access token"
1230
1237
  };
@@ -1233,7 +1240,7 @@ async function pollProviderAuth(params) {
1233
1240
  const classified = classifyMiniMaxErrorStatus(message);
1234
1241
  if (classified === "denied" || classified === "expired") authSessions.delete(sessionId);
1235
1242
  return {
1236
- provider: providerName,
1243
+ provider: providerId,
1237
1244
  status: classified,
1238
1245
  message
1239
1246
  };
@@ -1242,7 +1249,7 @@ async function pollProviderAuth(params) {
1242
1249
  session.intervalMs = nextPollMs;
1243
1250
  authSessions.set(sessionId, session);
1244
1251
  return {
1245
- provider: providerName,
1252
+ provider: providerId,
1246
1253
  status: "pending",
1247
1254
  nextPollMs
1248
1255
  };
@@ -1252,7 +1259,7 @@ async function pollProviderAuth(params) {
1252
1259
  if (!response.ok) {
1253
1260
  const errorCode = payload.error?.trim().toLowerCase();
1254
1261
  if (errorCode === "authorization_pending") return {
1255
- provider: providerName,
1262
+ provider: providerId,
1256
1263
  status: "pending",
1257
1264
  nextPollMs: session.intervalMs
1258
1265
  };
@@ -1261,7 +1268,7 @@ async function pollProviderAuth(params) {
1261
1268
  session.intervalMs = nextPollMs;
1262
1269
  authSessions.set(sessionId, session);
1263
1270
  return {
1264
- provider: providerName,
1271
+ provider: providerId,
1265
1272
  status: "pending",
1266
1273
  nextPollMs
1267
1274
  };
@@ -1269,7 +1276,7 @@ async function pollProviderAuth(params) {
1269
1276
  if (errorCode === "access_denied") {
1270
1277
  authSessions.delete(sessionId);
1271
1278
  return {
1272
- provider: providerName,
1279
+ provider: providerId,
1273
1280
  status: "denied",
1274
1281
  message: payload.error_description || "authorization denied"
1275
1282
  };
@@ -1277,38 +1284,40 @@ async function pollProviderAuth(params) {
1277
1284
  if (errorCode === "expired_token") {
1278
1285
  authSessions.delete(sessionId);
1279
1286
  return {
1280
- provider: providerName,
1287
+ provider: providerId,
1281
1288
  status: "expired",
1282
1289
  message: payload.error_description || "authorization session expired"
1283
1290
  };
1284
1291
  }
1285
1292
  return {
1286
- provider: providerName,
1293
+ provider: providerId,
1287
1294
  status: "error",
1288
1295
  message: payload.error_description || payload.error || response.statusText || "authorization failed"
1289
1296
  };
1290
1297
  }
1291
1298
  accessToken = payload.access_token?.trim() ?? "";
1292
1299
  if (!accessToken) return {
1293
- provider: providerName,
1300
+ provider: providerId,
1294
1301
  status: "error",
1295
1302
  message: "provider token response missing access token"
1296
1303
  };
1297
1304
  }
1298
1305
  setProviderApiKey({
1299
1306
  configPath,
1300
- provider: providerName,
1307
+ provider: providerId,
1301
1308
  accessToken,
1302
1309
  defaultApiBase: session.defaultApiBase
1303
1310
  });
1304
1311
  authSessions.delete(sessionId);
1305
1312
  return {
1306
- provider: providerName,
1313
+ provider: providerId,
1307
1314
  status: "authorized"
1308
1315
  };
1309
1316
  }
1310
- async function importProviderAuthFromCli(configPath, providerName) {
1311
- const spec = findServerBuiltinProviderByName(providerName);
1317
+ async function importProviderAuthFromCli(configPath, providerId) {
1318
+ const target = resolveProviderAuthTarget(configPath, providerId);
1319
+ if (!target) return null;
1320
+ const spec = findServerBuiltinProviderByName(target.providerType);
1312
1321
  if (!spec?.auth || spec.auth.kind !== "device_code" || !spec.auth.cliCredential) return null;
1313
1322
  const credentialPath = resolveHomePath(spec.auth.cliCredential.path);
1314
1323
  if (!credentialPath) throw new Error("provider cli credential path is empty");
@@ -1334,12 +1343,12 @@ async function importProviderAuthFromCli(configPath, providerName) {
1334
1343
  if (typeof expiresAtMs === "number" && expiresAtMs <= Date.now()) throw new Error("CLI credential has expired, please login again");
1335
1344
  setProviderApiKey({
1336
1345
  configPath,
1337
- provider: providerName,
1346
+ provider: providerId,
1338
1347
  accessToken,
1339
1348
  defaultApiBase: spec.defaultApiBase
1340
1349
  });
1341
1350
  return {
1342
- provider: providerName,
1351
+ provider: providerId,
1343
1352
  status: "imported",
1344
1353
  source: "cli",
1345
1354
  expiresAt: expiresAtMs ? new Date(expiresAtMs).toISOString() : void 0
@@ -1405,6 +1414,13 @@ var ConfigRoutesController = class {
1405
1414
  const config = loadConfigOrDefault(this.options.configPath);
1406
1415
  return c.json(ok(buildConfigMeta(config, this.getExtensionConfigProjectionOptions())));
1407
1416
  };
1417
+ listProviders = (c) => {
1418
+ const config = loadConfigOrDefault(this.options.configPath);
1419
+ return c.json(ok(buildProvidersView(config)));
1420
+ };
1421
+ listProviderTemplates = (c) => {
1422
+ return c.json(ok(buildProviderTemplatesView()));
1423
+ };
1408
1424
  getConfigSchema = (c) => {
1409
1425
  const config = loadConfigOrDefault(this.options.configPath);
1410
1426
  return c.json(ok(buildConfigSchemaView(config, this.getExtensionConfigProjectionOptions())));
@@ -1435,35 +1451,36 @@ var ConfigRoutesController = class {
1435
1451
  return c.json(ok(result));
1436
1452
  };
1437
1453
  updateProvider = async (c) => {
1438
- const provider = c.req.param("provider");
1454
+ const providerId = c.req.param("providerId");
1439
1455
  const body = await readJson(c.req.raw);
1440
1456
  if (!body.ok) return c.json(err("INVALID_BODY", "invalid json body"), 400);
1441
- const result = updateProvider(this.options.configPath, provider, body.data);
1442
- if (!result) return c.json(err("NOT_FOUND", `unknown provider: ${provider}`), 404);
1443
- await this.publishConfigUpdates([`providers.${provider}`]);
1457
+ const result = updateProvider(this.options.configPath, providerId, body.data);
1458
+ if (!result) return c.json(err("NOT_FOUND", `unknown provider: ${providerId}`), 404);
1459
+ await this.publishConfigUpdates([`providers.${providerId}`]);
1444
1460
  return c.json(ok(result));
1445
1461
  };
1446
1462
  createProvider = async (c) => {
1447
1463
  const body = await readJson(c.req.raw);
1448
1464
  if (!body.ok) return c.json(err("INVALID_BODY", "invalid json body"), 400);
1449
- const result = createCustomProvider(this.options.configPath, body.data);
1450
- await this.publishConfigUpdates([`providers.${result.name}`]);
1465
+ const result = createProvider(this.options.configPath, body.data);
1466
+ if (!result) return c.json(err("PROVIDER_EXISTS", "provider already exists"), 409);
1467
+ await this.publishConfigUpdates([`providers.${result.providerId}`]);
1451
1468
  return c.json(ok({
1452
- name: result.name,
1469
+ providerId: result.providerId,
1453
1470
  provider: result.provider
1454
1471
  }));
1455
1472
  };
1456
1473
  deleteProvider = async (c) => {
1457
- const provider = c.req.param("provider");
1458
- if (deleteCustomProvider(this.options.configPath, provider) === null) return c.json(err("NOT_FOUND", `custom provider not found: ${provider}`), 404);
1459
- await this.publishConfigUpdates([`providers.${provider}`]);
1474
+ const providerId = c.req.param("providerId");
1475
+ if (deleteProvider(this.options.configPath, providerId) === null) return c.json(err("NOT_FOUND", `provider not found: ${providerId}`), 404);
1476
+ await this.publishConfigUpdates([`providers.${providerId}`]);
1460
1477
  return c.json(ok({
1461
1478
  deleted: true,
1462
- provider
1479
+ providerId
1463
1480
  }));
1464
1481
  };
1465
1482
  testProviderConnection = async (c) => {
1466
- const provider = c.req.param("provider");
1483
+ const provider = c.req.param("providerId");
1467
1484
  const body = await readJson(c.req.raw);
1468
1485
  if (!body.ok) return c.json(err("INVALID_BODY", "invalid json body"), 400);
1469
1486
  const result = await testProviderConnection(this.options.configPath, provider, body.data, this.options.kernel.llmProviders);
@@ -1471,7 +1488,7 @@ var ConfigRoutesController = class {
1471
1488
  return c.json(ok(result));
1472
1489
  };
1473
1490
  startProviderAuth = async (c) => {
1474
- const provider = c.req.param("provider");
1491
+ const provider = c.req.param("providerId");
1475
1492
  let payload = {};
1476
1493
  const rawBody = await c.req.raw.text();
1477
1494
  if (rawBody.trim().length > 0) try {
@@ -1490,7 +1507,7 @@ var ConfigRoutesController = class {
1490
1507
  }
1491
1508
  };
1492
1509
  pollProviderAuth = async (c) => {
1493
- const provider = c.req.param("provider");
1510
+ const provider = c.req.param("providerId");
1494
1511
  const body = await readJson(c.req.raw);
1495
1512
  if (!body.ok) return c.json(err("INVALID_BODY", "invalid json body"), 400);
1496
1513
  const sessionId = typeof body.data.sessionId === "string" ? body.data.sessionId.trim() : "";
@@ -1505,7 +1522,7 @@ var ConfigRoutesController = class {
1505
1522
  return c.json(ok(result));
1506
1523
  };
1507
1524
  importProviderAuthFromCli = async (c) => {
1508
- const provider = c.req.param("provider");
1525
+ const provider = c.req.param("providerId");
1509
1526
  try {
1510
1527
  const result = await importProviderAuthFromCli(this.options.configPath, provider);
1511
1528
  if (!result) return c.json(err("NOT_SUPPORTED", `provider cli auth import is not supported: ${provider}`), 404);
@@ -1872,11 +1889,6 @@ const PREFERRED_PROVIDER_ORDER_INDEX = new Map([
1872
1889
  ].map((name, index) => [name, index]));
1873
1890
  const BUILTIN_PROVIDERS = listServerBuiltinProviders();
1874
1891
  const BUILTIN_PROVIDER_NAMES = new Set(BUILTIN_PROVIDERS.map((spec) => spec.name));
1875
- const CUSTOM_PROVIDER_WIRE_API_OPTIONS = [
1876
- "auto",
1877
- "chat",
1878
- "responses"
1879
- ];
1880
1892
  const CUSTOM_PROVIDER_PREFIX = "custom-";
1881
1893
  const PROVIDER_TEST_MAX_TOKENS = 16;
1882
1894
  function normalizeOptionalDisplayName(value) {
@@ -1894,13 +1906,8 @@ function resolveCustomProviderFallbackDisplayName(name) {
1894
1906
  }
1895
1907
  return name;
1896
1908
  }
1897
- function resolveProviderDisplayName(providerName, provider, spec) {
1898
- const configDisplayName = normalizeOptionalDisplayName(provider?.displayName);
1899
- if (isCustomProviderName(providerName)) return configDisplayName ?? resolveCustomProviderFallbackDisplayName(providerName);
1900
- return spec?.displayName ?? configDisplayName ?? spec?.name;
1901
- }
1902
- function listCustomProviderNames(config) {
1903
- return Object.keys(config.providers).filter((name) => isCustomProviderName(name));
1909
+ function resolveProviderInstanceDisplayName(providerId, provider, spec) {
1910
+ return normalizeOptionalDisplayName(provider?.displayName) ?? spec?.displayName ?? (providerId.startsWith(CUSTOM_PROVIDER_PREFIX) ? resolveCustomProviderFallbackDisplayName(providerId) : providerId);
1904
1911
  }
1905
1912
  function findNextCustomProviderName(config) {
1906
1913
  const providers = config.providers;
@@ -1908,16 +1915,39 @@ function findNextCustomProviderName(config) {
1908
1915
  while (providers[`${CUSTOM_PROVIDER_PREFIX}${index}`]) index += 1;
1909
1916
  return `${CUSTOM_PROVIDER_PREFIX}${index}`;
1910
1917
  }
1911
- function ensureProviderConfig(config, providerName) {
1918
+ function normalizeProviderId(value) {
1919
+ if (typeof value !== "string") return null;
1920
+ const trimmed = value.trim();
1921
+ if (!trimmed || trimmed.includes("/")) return null;
1922
+ return trimmed;
1923
+ }
1924
+ function resolveProviderType(providerId, provider) {
1925
+ const configuredType = normalizeProviderId(provider?.providerType);
1926
+ if (configuredType && findServerBuiltinProviderByName(configuredType)) return configuredType;
1927
+ if (findServerBuiltinProviderByName(providerId)) return providerId;
1928
+ return null;
1929
+ }
1930
+ function findNextProviderId(config, baseProviderId) {
1912
1931
  const providers = config.providers;
1913
- const existing = providers[providerName];
1914
- if (existing) return existing;
1915
- if (isCustomProviderName(providerName)) return null;
1916
- const spec = findServerBuiltinProviderByName(providerName);
1917
- if (!spec) return null;
1918
- const created = createDefaultProviderConfigFromSpec(spec);
1919
- providers[providerName] = created;
1920
- return created;
1932
+ let providerId = baseProviderId;
1933
+ let index = 2;
1934
+ while (providers[providerId]) {
1935
+ providerId = `${baseProviderId}-${index}`;
1936
+ index += 1;
1937
+ }
1938
+ return providerId;
1939
+ }
1940
+ function resolveProviderDisplayNameSuffix(providerId, baseProviderId) {
1941
+ if (providerId === baseProviderId) return "";
1942
+ const suffix = providerId.slice(baseProviderId.length + 1).trim();
1943
+ return suffix ? ` ${suffix}` : "";
1944
+ }
1945
+ function buildProviderScopedModels(providerId, models) {
1946
+ return normalizeModelList(models).map((model) => {
1947
+ const slashIndex = model.indexOf("/");
1948
+ const modelSuffix = slashIndex >= 0 ? model.slice(slashIndex + 1).trim() : model;
1949
+ return modelSuffix ? `${providerId}/${modelSuffix}` : "";
1950
+ }).filter(Boolean);
1921
1951
  }
1922
1952
  function clearSecretRefsByPrefix(refs, pathPrefix) {
1923
1953
  return Object.fromEntries(Object.entries(refs).filter(([key]) => key !== pathPrefix && !key.startsWith(`${pathPrefix}.`)));
@@ -2082,13 +2112,18 @@ function normalizeModelList(input) {
2082
2112
  }
2083
2113
  return [...deduped];
2084
2114
  }
2085
- function toProviderView(config, provider, providerName, uiHints, spec) {
2086
- const apiKeyRefSet = hasSecretRef(config, `providers.${providerName}.apiKey`);
2115
+ function toProviderView(config, provider, providerId, uiHints, spec) {
2116
+ const providerType = resolveProviderType(providerId, provider);
2117
+ const apiKeyRefSet = hasSecretRef(config, `providers.${providerId}.apiKey`);
2087
2118
  const masked = maskApiKey(provider.apiKey);
2088
- const extraHeaders = provider.extraHeaders && Object.keys(provider.extraHeaders).length > 0 ? sanitizePublicConfigValue(provider.extraHeaders, `providers.${providerName}.extraHeaders`, uiHints) : null;
2119
+ const extraHeaders = provider.extraHeaders && Object.keys(provider.extraHeaders).length > 0 ? sanitizePublicConfigValue(provider.extraHeaders, `providers.${providerId}.extraHeaders`, uiHints) : null;
2089
2120
  const view = {
2121
+ providerId,
2122
+ providerType,
2123
+ isBuiltInType: providerType !== null,
2124
+ isCustom: providerType === null,
2090
2125
  enabled: provider.enabled !== false,
2091
- displayName: resolveProviderDisplayName(providerName, provider, spec),
2126
+ displayName: resolveProviderInstanceDisplayName(providerId, provider, spec),
2092
2127
  apiKeySet: masked.apiKeySet || apiKeyRefSet,
2093
2128
  apiKeyMasked: masked.apiKeyMasked ?? (apiKeyRefSet ? "****" : void 0),
2094
2129
  apiBase: provider.apiBase ?? null,
@@ -2096,14 +2131,17 @@ function toProviderView(config, provider, providerName, uiHints, spec) {
2096
2131
  models: normalizeModelList(provider.models ?? []),
2097
2132
  modelConfig: normalizeProviderModelConfig(provider.modelConfig ?? {})
2098
2133
  };
2099
- if (Boolean(spec?.supportsWireApi) || isCustomProviderName(providerName)) view.wireApi = provider.wireApi ?? spec?.defaultWireApi ?? "auto";
2134
+ if (Boolean(spec?.supportsWireApi) || providerType === null) view.wireApi = provider.wireApi ?? spec?.defaultWireApi ?? "auto";
2100
2135
  return view;
2101
2136
  }
2102
2137
  function buildConfigView(config, options) {
2103
2138
  const uiHints = buildUiHints(config, options);
2104
2139
  const projectedChannels = getProjectedChannelMap(config, options);
2105
2140
  const providers = {};
2106
- for (const [name, provider] of Object.entries(config.providers)) providers[name] = toProviderView(config, provider, name, uiHints, findServerBuiltinProviderByName(name));
2141
+ for (const [providerId, provider] of Object.entries(config.providers)) {
2142
+ const providerConfig = provider;
2143
+ providers[providerId] = toProviderView(config, providerConfig, providerId, uiHints, findServerBuiltinProviderByName(resolveProviderType(providerId, providerConfig) ?? ""));
2144
+ }
2107
2145
  return {
2108
2146
  companion: sanitizePublicConfigValue(config.companion, "companion", uiHints),
2109
2147
  agents: sanitizePublicConfigValue(config.agents, "agents", uiHints),
@@ -2182,13 +2220,18 @@ function clearSecretRef(refs, path) {
2182
2220
  return nextRefs;
2183
2221
  }
2184
2222
  function buildConfigMeta(config, options) {
2185
- const configProviders = config.providers;
2186
- const builtinProviders = BUILTIN_PROVIDERS.map((spec) => {
2187
- const providerConfig = configProviders[spec.name];
2223
+ return {
2224
+ search: SEARCH_PROVIDER_META,
2225
+ channels: buildProjectedChannelMeta(config, options)
2226
+ };
2227
+ }
2228
+ function buildProviderTemplatesView() {
2229
+ return { providerTemplates: BUILTIN_PROVIDERS.map((spec) => {
2188
2230
  return {
2189
- name: spec.name,
2190
- displayName: resolveProviderDisplayName(spec.name, providerConfig, spec),
2191
- isCustom: false,
2231
+ id: spec.name,
2232
+ providerType: spec.name,
2233
+ displayName: spec.displayName ?? spec.name,
2234
+ apiProtocol: spec.apiProtocol,
2192
2235
  modelPrefix: spec.modelPrefix,
2193
2236
  keywords: spec.keywords,
2194
2237
  envKey: spec.envKey,
@@ -2216,43 +2259,22 @@ function buildConfigMeta(config, options) {
2216
2259
  defaultWireApi: spec.defaultWireApi
2217
2260
  };
2218
2261
  }).sort((left, right) => {
2219
- const leftRank = PREFERRED_PROVIDER_ORDER_INDEX.get(left.name);
2220
- const rightRank = PREFERRED_PROVIDER_ORDER_INDEX.get(right.name);
2262
+ const leftRank = PREFERRED_PROVIDER_ORDER_INDEX.get(left.id);
2263
+ const rightRank = PREFERRED_PROVIDER_ORDER_INDEX.get(right.id);
2221
2264
  if (leftRank !== void 0 && rightRank !== void 0) return leftRank - rightRank;
2222
2265
  if (leftRank !== void 0) return -1;
2223
2266
  if (rightRank !== void 0) return 1;
2224
- return left.name.localeCompare(right.name);
2225
- });
2226
- return {
2227
- providers: [...listCustomProviderNames(config).sort((left, right) => left.localeCompare(right, void 0, {
2228
- numeric: true,
2229
- sensitivity: "base"
2230
- })).map((name) => {
2231
- const providerConfig = configProviders[name];
2232
- const displayName = resolveProviderDisplayName(name, providerConfig);
2233
- return {
2234
- name,
2235
- displayName,
2236
- isCustom: true,
2237
- modelPrefix: name,
2238
- keywords: normalizeModelList([name, displayName ?? ""]),
2239
- envKey: "OPENAI_API_KEY",
2240
- isGateway: false,
2241
- isLocal: false,
2242
- defaultApiBase: void 0,
2243
- logo: void 0,
2244
- apiBaseHelp: void 0,
2245
- auth: void 0,
2246
- defaultModels: [],
2247
- modelConfig: {},
2248
- supportsWireApi: true,
2249
- wireApiOptions: CUSTOM_PROVIDER_WIRE_API_OPTIONS,
2250
- defaultWireApi: "auto"
2251
- };
2252
- }), ...builtinProviders],
2253
- search: SEARCH_PROVIDER_META,
2254
- channels: buildProjectedChannelMeta(config, options)
2255
- };
2267
+ return left.id.localeCompare(right.id);
2268
+ }) };
2269
+ }
2270
+ function buildProvidersView(config) {
2271
+ const uiHints = buildUiHints(config);
2272
+ const providers = {};
2273
+ for (const [providerId, provider] of Object.entries(config.providers)) {
2274
+ const providerConfig = provider;
2275
+ providers[providerId] = toProviderView(config, providerConfig, providerId, uiHints, findServerBuiltinProviderByName(resolveProviderType(providerId, providerConfig) ?? ""));
2276
+ }
2277
+ return { providers };
2256
2278
  }
2257
2279
  function buildConfigSchemaView(_config, options) {
2258
2280
  const base = buildConfigSchema({ version: getPackageVersion() });
@@ -2315,60 +2337,67 @@ function updateModel(configPath, patch) {
2315
2337
  saveConfig(next, configPath);
2316
2338
  return buildConfigView(next);
2317
2339
  }
2318
- function updateProvider(configPath, providerName, patch) {
2340
+ function updateProvider(configPath, providerId, patch) {
2319
2341
  const config = loadConfigOrDefault(configPath);
2320
- const provider = ensureProviderConfig(config, providerName);
2342
+ const provider = config.providers[providerId];
2321
2343
  if (!provider) return null;
2322
- const spec = findServerBuiltinProviderByName(providerName);
2323
- const isCustom = isCustomProviderName(providerName);
2324
- if (Object.prototype.hasOwnProperty.call(patch, "displayName") && isCustom) provider.displayName = normalizeOptionalDisplayName(patch.displayName) ?? "";
2344
+ const currentProviderType = resolveProviderType(providerId, provider);
2345
+ const spec = findServerBuiltinProviderByName((Object.prototype.hasOwnProperty.call(patch, "providerType") ? normalizeProviderId(patch.providerType) : currentProviderType) ?? "");
2346
+ if (Object.prototype.hasOwnProperty.call(patch, "providerType")) provider.providerType = spec?.name ?? null;
2347
+ if (Object.prototype.hasOwnProperty.call(patch, "displayName")) provider.displayName = normalizeOptionalDisplayName(patch.displayName) ?? "";
2325
2348
  if (Object.prototype.hasOwnProperty.call(patch, "enabled")) provider.enabled = patch.enabled !== false;
2326
2349
  if (Object.prototype.hasOwnProperty.call(patch, "apiKey")) {
2327
2350
  provider.apiKey = patch.apiKey ?? "";
2328
- config.secrets.refs = clearSecretRef(config.secrets.refs, `providers.${providerName}.apiKey`);
2351
+ config.secrets.refs = clearSecretRef(config.secrets.refs, `providers.${providerId}.apiKey`);
2329
2352
  }
2330
2353
  if (Object.prototype.hasOwnProperty.call(patch, "apiBase")) provider.apiBase = patch.apiBase ?? null;
2331
2354
  if (Object.prototype.hasOwnProperty.call(patch, "extraHeaders")) provider.extraHeaders = patch.extraHeaders ?? null;
2332
- if (Object.prototype.hasOwnProperty.call(patch, "wireApi") && (spec?.supportsWireApi || isCustom)) provider.wireApi = patch.wireApi ?? spec?.defaultWireApi ?? "auto";
2355
+ if (Object.prototype.hasOwnProperty.call(patch, "wireApi") && (spec?.supportsWireApi || !spec)) provider.wireApi = patch.wireApi ?? spec?.defaultWireApi ?? "auto";
2333
2356
  if (Object.prototype.hasOwnProperty.call(patch, "models")) provider.models = normalizeModelList(patch.models ?? []);
2334
2357
  if (Object.prototype.hasOwnProperty.call(patch, "modelConfig")) provider.modelConfig = normalizeProviderModelConfig(patch.modelConfig ?? {});
2335
2358
  const next = ConfigSchema.parse(config);
2336
2359
  saveConfig(next, configPath);
2337
2360
  const uiHints = buildUiHints(next);
2338
- const updated = next.providers[providerName];
2339
- return toProviderView(next, updated, providerName, uiHints, spec ?? void 0);
2361
+ const updated = next.providers[providerId];
2362
+ return toProviderView(next, updated, providerId, uiHints, spec ?? void 0);
2340
2363
  }
2341
- function createCustomProvider(configPath, patch = {}) {
2364
+ function createProvider(configPath, patch = {}) {
2342
2365
  const config = loadConfigOrDefault(configPath);
2343
- const providerName = findNextCustomProviderName(config);
2344
2366
  const providers = config.providers;
2345
- const generatedDisplayName = resolveCustomProviderFallbackDisplayName(providerName);
2346
- providers[providerName] = {
2367
+ const requestedProviderType = normalizeProviderId(patch.providerType);
2368
+ const spec = requestedProviderType ? findServerBuiltinProviderByName(requestedProviderType) : void 0;
2369
+ const fallbackProviderId = spec ? spec.name : findNextCustomProviderName(config);
2370
+ const requestedProviderId = normalizeProviderId(patch.providerId);
2371
+ if (requestedProviderId && providers[requestedProviderId]) return null;
2372
+ const providerId = requestedProviderId ? requestedProviderId : findNextProviderId(config, fallbackProviderId);
2373
+ const generatedDisplayName = spec ? `${spec.displayName}${resolveProviderDisplayNameSuffix(providerId, spec.name)}` : resolveCustomProviderFallbackDisplayName(providerId);
2374
+ const defaultModels = spec ? buildProviderScopedModels(providerId, spec.defaultModels ?? []) : [];
2375
+ providers[providerId] = {
2347
2376
  enabled: patch.enabled !== false,
2377
+ providerType: spec?.name ?? null,
2348
2378
  displayName: normalizeOptionalDisplayName(patch.displayName) ?? generatedDisplayName,
2349
2379
  apiKey: normalizeOptionalString(patch.apiKey) ?? "",
2350
- apiBase: normalizeOptionalString(patch.apiBase),
2380
+ apiBase: normalizeOptionalString(patch.apiBase) ?? spec?.defaultApiBase ?? null,
2351
2381
  extraHeaders: normalizeHeaders(patch.extraHeaders ?? null),
2352
- wireApi: patch.wireApi ?? "auto",
2353
- models: normalizeModelList(patch.models ?? []),
2354
- modelConfig: normalizeProviderModelConfig(patch.modelConfig ?? {})
2382
+ wireApi: patch.wireApi ?? spec?.defaultWireApi ?? "auto",
2383
+ models: Object.prototype.hasOwnProperty.call(patch, "models") ? normalizeModelList(patch.models ?? []) : defaultModels,
2384
+ modelConfig: normalizeProviderModelConfig(patch.modelConfig ?? spec?.modelConfig ?? {})
2355
2385
  };
2356
2386
  const next = ConfigSchema.parse(config);
2357
2387
  saveConfig(next, configPath);
2358
2388
  const uiHints = buildUiHints(next);
2359
- const created = next.providers[providerName];
2389
+ const created = next.providers[providerId];
2360
2390
  return {
2361
- name: providerName,
2362
- provider: toProviderView(next, created, providerName, uiHints)
2391
+ providerId,
2392
+ provider: toProviderView(next, created, providerId, uiHints, spec)
2363
2393
  };
2364
2394
  }
2365
- function deleteCustomProvider(configPath, providerName) {
2366
- if (!isCustomProviderName(providerName)) return null;
2395
+ function deleteProvider(configPath, providerId) {
2367
2396
  const config = loadConfigOrDefault(configPath);
2368
2397
  const providers = config.providers;
2369
- if (!providers[providerName]) return null;
2370
- delete providers[providerName];
2371
- config.secrets.refs = clearSecretRefsByPrefix(config.secrets.refs, `providers.${providerName}`);
2398
+ if (!providers[providerId]) return null;
2399
+ delete providers[providerId];
2400
+ config.secrets.refs = clearSecretRefsByPrefix(config.secrets.refs, `providers.${providerId}`);
2372
2401
  saveConfig(ConfigSchema.parse(config), configPath);
2373
2402
  return true;
2374
2403
  }
@@ -2408,32 +2437,35 @@ function buildScopedProviderModel(providerName, model, spec) {
2408
2437
  if (!prefix) return trimmed;
2409
2438
  return `${prefix}/${trimmed}`;
2410
2439
  }
2411
- function resolveTestModel(config, providerName, requestedModel, provider, spec) {
2412
- if (requestedModel) {
2413
- if (isCustomProviderName(providerName)) {
2414
- const prefix = `${providerName}/`;
2415
- if (requestedModel.startsWith(prefix)) return requestedModel.slice(prefix.length) || null;
2416
- }
2417
- return requestedModel;
2418
- }
2419
- const providerModels = normalizeModelList(provider.models ?? []).map((modelId) => buildScopedProviderModel(providerName, modelId, spec)).filter((modelId) => modelId.length > 0);
2440
+ function stripProviderIdPrefix(providerId, model) {
2441
+ const prefix = `${providerId}/`;
2442
+ if (!model.startsWith(prefix)) return model;
2443
+ return model.slice(prefix.length).trim() || model;
2444
+ }
2445
+ function resolveTestModel(config, providerId, requestedModel, provider, spec) {
2446
+ if (requestedModel) return spec ? requestedModel.replace(`${providerId}/`, `${spec.name}/`) : stripProviderIdPrefix(providerId, requestedModel);
2447
+ const providerModels = normalizeModelList(provider.models ?? []).map((modelId) => {
2448
+ const providerModel = stripProviderIdPrefix(providerId, modelId);
2449
+ return spec ? buildScopedProviderModel(spec.name, providerModel, spec) : providerModel;
2450
+ }).filter((modelId) => modelId.length > 0);
2420
2451
  if (providerModels.length > 0) return providerModels[0];
2421
2452
  const defaultModel = normalizeOptionalString(config.agents.defaults.model);
2422
2453
  if (defaultModel) {
2423
2454
  const routedProvider = getProviderName(config, defaultModel);
2424
- if (!routedProvider || routedProvider === providerName) return defaultModel;
2455
+ if (!routedProvider || routedProvider === providerId) return spec ? defaultModel.replace(`${providerId}/`, `${spec.name}/`) : stripProviderIdPrefix(providerId, defaultModel);
2425
2456
  }
2426
- if (isCustomProviderName(providerName)) return null;
2457
+ if (!spec) return null;
2427
2458
  return normalizeModelList(spec?.defaultModels ?? [])[0] ?? null ?? defaultModel ?? null;
2428
2459
  }
2429
2460
  function stringifyError(error) {
2430
2461
  return (error instanceof Error ? error.message : String(error)).replace(/\s+/g, " ").trim();
2431
2462
  }
2432
- async function testProviderConnection(configPath, providerName, patch, providerManager) {
2463
+ async function testProviderConnection(configPath, providerId, patch, providerManager) {
2433
2464
  const config = loadConfigOrDefault(configPath);
2434
- const provider = ensureProviderConfig(config, providerName);
2465
+ const provider = config.providers[providerId];
2435
2466
  if (!provider) return null;
2436
- const spec = findServerBuiltinProviderByName(providerName);
2467
+ const providerType = resolveProviderType(providerId, provider);
2468
+ const spec = findServerBuiltinProviderByName(providerType ?? "");
2437
2469
  const hasApiKeyPatch = Object.prototype.hasOwnProperty.call(patch, "apiKey");
2438
2470
  const providedApiKey = normalizeOptionalString(patch.apiKey);
2439
2471
  const currentApiKey = normalizeOptionalString(provider.apiKey);
@@ -2443,32 +2475,31 @@ async function testProviderConnection(configPath, providerName, patch, providerM
2443
2475
  const currentApiBase = normalizeOptionalString(provider.apiBase);
2444
2476
  const apiBase = hasApiBasePatch ? patchedApiBase ?? spec?.defaultApiBase ?? null : currentApiBase ?? spec?.defaultApiBase ?? null;
2445
2477
  const extraHeaders = Object.prototype.hasOwnProperty.call(patch, "extraHeaders") ? normalizeHeaders(patch.extraHeaders ?? null) : normalizeHeaders(provider.extraHeaders ?? null);
2446
- const isCustom = isCustomProviderName(providerName);
2447
- const wireApi = spec?.supportsWireApi || isCustom ? patch.wireApi ?? provider.wireApi ?? spec?.defaultWireApi ?? "auto" : null;
2478
+ const wireApi = spec?.supportsWireApi || !spec ? patch.wireApi ?? provider.wireApi ?? spec?.defaultWireApi ?? "auto" : null;
2448
2479
  if (!apiKey && !spec?.isLocal) return {
2449
2480
  success: false,
2450
- provider: providerName,
2481
+ provider: providerId,
2451
2482
  latencyMs: 0,
2452
2483
  message: "API key is required before testing the connection."
2453
2484
  };
2454
- const model = resolveTestModel(config, providerName, normalizeOptionalString(patch.model), provider, spec ?? void 0);
2485
+ const model = resolveTestModel(config, providerId, normalizeOptionalString(patch.model), provider, spec ?? void 0);
2455
2486
  if (!model) return {
2456
2487
  success: false,
2457
- provider: providerName,
2488
+ provider: providerId,
2458
2489
  latencyMs: 0,
2459
2490
  message: "No test model found. Configure provider models or set a default model for this provider, then try again."
2460
2491
  };
2461
2492
  const startedAtMs = Date.now();
2462
2493
  if (!providerManager) return {
2463
2494
  success: false,
2464
- provider: providerName,
2495
+ provider: providerId,
2465
2496
  model,
2466
2497
  latencyMs: Date.now() - startedAtMs,
2467
2498
  message: "Provider manager is unavailable."
2468
2499
  };
2469
2500
  try {
2470
2501
  await providerManager.testConnection({
2471
- providerName,
2502
+ providerName: providerType,
2472
2503
  apiKey,
2473
2504
  apiBase,
2474
2505
  defaultModel: model,
@@ -2482,7 +2513,7 @@ async function testProviderConnection(configPath, providerName, patch, providerM
2482
2513
  });
2483
2514
  return {
2484
2515
  success: true,
2485
- provider: providerName,
2516
+ provider: providerId,
2486
2517
  model,
2487
2518
  latencyMs: Date.now() - startedAtMs,
2488
2519
  message: "Connection test passed."
@@ -2490,7 +2521,7 @@ async function testProviderConnection(configPath, providerName, patch, providerM
2490
2521
  } catch (error) {
2491
2522
  return {
2492
2523
  success: false,
2493
- provider: providerName,
2524
+ provider: providerId,
2494
2525
  model,
2495
2526
  latencyMs: Date.now() - startedAtMs,
2496
2527
  message: stringifyError(error) || "Connection test failed."
@@ -3306,6 +3337,8 @@ var McpMarketplaceController = class {
3306
3337
  //#endregion
3307
3338
  //#region src/features/marketplace/utils/marketplace-installed.utils.ts
3308
3339
  const getWorkspacePathFromConfig = NextclawCore.getWorkspacePathFromConfig;
3340
+ const MARKETPLACE_INSTALL_STATE_FILE = ".nextclaw-install.json";
3341
+ const LEGACY_MARKETPLACE_INSTALL_STATE_FILE = ".nextclaw-marketplace.json";
3309
3342
  function createSkillsLoader(workspace) {
3310
3343
  const ctor = NextclawCore.SkillsLoader;
3311
3344
  if (!ctor) return null;
@@ -3319,14 +3352,21 @@ function collectInstalledSkillRecords(options) {
3319
3352
  const metadata = skillsLoader?.getSkillMetadata?.(skill);
3320
3353
  const description = readNonEmptyString(metadata?.description);
3321
3354
  const descriptionZh = readNonEmptyString(metadata?.description_zh) ?? readNonEmptyString(metadata?.descriptionZh) ?? readNonEmptyString(MARKETPLACE_ZH_COPY_BY_SLUG[skill.name]?.description);
3355
+ const marketplaceState = readMarketplaceSkillInstallState(dirname(skill.path));
3356
+ const origin = marketplaceState ? "marketplace" : void 0;
3357
+ const catalogSlug = marketplaceState?.slug;
3358
+ const installedAt = marketplaceState?.installedAt;
3322
3359
  return {
3323
3360
  type: "skill",
3324
3361
  id: skill.name,
3325
3362
  spec: skill.name,
3326
3363
  label: skill.name,
3327
- ...description ? { description } : {},
3328
- ...descriptionZh ? { descriptionZh } : {},
3364
+ description,
3365
+ descriptionZh,
3329
3366
  source: skill.source,
3367
+ origin,
3368
+ catalogSlug,
3369
+ installedAt,
3330
3370
  enabled,
3331
3371
  runtimeStatus: enabled ? "enabled" : "disabled"
3332
3372
  };
@@ -3336,6 +3376,20 @@ function collectInstalledSkillRecords(options) {
3336
3376
  records
3337
3377
  };
3338
3378
  }
3379
+ function readMarketplaceSkillInstallState(destinationDir) {
3380
+ const statePath = [MARKETPLACE_INSTALL_STATE_FILE, LEGACY_MARKETPLACE_INSTALL_STATE_FILE].map((file) => join(destinationDir, file)).find((path) => existsSync(path));
3381
+ if (!statePath) return null;
3382
+ try {
3383
+ const parsed = JSON.parse(readFileSync(statePath, "utf8"));
3384
+ if (parsed.schemaVersion !== 1 || parsed.type !== "skill" || parsed.source !== "marketplace" || typeof parsed.slug !== "string") return null;
3385
+ return {
3386
+ slug: parsed.slug,
3387
+ installedAt: typeof parsed.installedAt === "string" ? parsed.installedAt : void 0
3388
+ };
3389
+ } catch {
3390
+ return null;
3391
+ }
3392
+ }
3339
3393
  function collectSkillMarketplaceInstalledView(options) {
3340
3394
  const installed = collectInstalledSkillRecords(options);
3341
3395
  return {
@@ -3390,9 +3444,24 @@ async function manageMarketplaceSkill(params) {
3390
3444
  const { body, options } = params;
3391
3445
  const action = body.action;
3392
3446
  const targetId = typeof body.id === "string" && body.id.trim().length > 0 ? body.id.trim() : typeof body.spec === "string" && body.spec.trim().length > 0 ? body.spec.trim() : "";
3393
- if (action !== "uninstall" || !targetId) throw new Error("INVALID_BODY:skill manage requires uninstall action and non-empty id/spec");
3447
+ if (action !== "update" && action !== "uninstall" || !targetId) throw new Error("INVALID_BODY:skill manage requires update/uninstall action and non-empty id/spec");
3394
3448
  const installer = options.marketplace?.installer;
3395
3449
  if (!installer) throw new Error("NOT_AVAILABLE:marketplace installer is not configured");
3450
+ if (action === "update") {
3451
+ if (!installer.updateSkill) throw new Error("NOT_AVAILABLE:skill update is not configured");
3452
+ const result = await installer.updateSkill({
3453
+ slug: targetId,
3454
+ force: body.force
3455
+ });
3456
+ emitConfigUpdated(options, "skills");
3457
+ return {
3458
+ type: "skill",
3459
+ action,
3460
+ id: targetId,
3461
+ message: result.message,
3462
+ output: result.output
3463
+ };
3464
+ }
3396
3465
  if (!installer.uninstallSkill) throw new Error("NOT_AVAILABLE:skill uninstall is not configured");
3397
3466
  const result = await installer.uninstallSkill(targetId);
3398
3467
  emitConfigUpdated(options, "skills");
@@ -4261,6 +4330,13 @@ var ServiceAppsRoutesController = class {
4261
4330
  return this.handleServiceAppError(c, error);
4262
4331
  }
4263
4332
  };
4333
+ deleteServiceApp = async (c) => {
4334
+ try {
4335
+ return c.json(ok(await this.params.serviceAppManager.deleteServiceApp(c.req.param("appId"))));
4336
+ } catch (error) {
4337
+ return this.handleServiceAppError(c, error);
4338
+ }
4339
+ };
4264
4340
  requireBridgeSession = (c) => {
4265
4341
  const token = c.req.raw.headers.get(PANEL_BRIDGE_SESSION_HEADER)?.trim();
4266
4342
  if (!token) throw new Error("panel app bridge session is required");
@@ -4684,182 +4760,8 @@ var UiRouteRegistry = class {
4684
4760
  ncpAsset.getAssetContent
4685
4761
  ]]);
4686
4762
  };
4687
- register = () => {
4688
- const { agents, app, auth, config, cron, ncpAsset, ncpSession, panelApps, serviceApps, remote, runtimeControl, runtimeUpdate, serverPath } = this.controllers;
4689
- this.mountRoutes([
4690
- [
4691
- "get",
4692
- "/api/health",
4693
- app.health
4694
- ],
4695
- [
4696
- "get",
4697
- "/api/app/meta",
4698
- app.appMeta
4699
- ],
4700
- [
4701
- "get",
4702
- "/api/runtime/bootstrap-status",
4703
- app.bootstrapStatus
4704
- ],
4705
- [
4706
- "get",
4707
- "/api/auth/status",
4708
- auth.getStatus
4709
- ],
4710
- [
4711
- "post",
4712
- "/api/auth/setup",
4713
- auth.setup
4714
- ],
4715
- [
4716
- "post",
4717
- "/api/auth/login",
4718
- auth.login
4719
- ],
4720
- [
4721
- "post",
4722
- "/api/auth/logout",
4723
- auth.logout
4724
- ],
4725
- [
4726
- "put",
4727
- "/api/auth/password",
4728
- auth.updatePassword
4729
- ],
4730
- [
4731
- "put",
4732
- "/api/auth/enabled",
4733
- auth.updateEnabled
4734
- ],
4735
- [
4736
- "post",
4737
- "/api/auth/bridge",
4738
- auth.issueBridgeSession
4739
- ],
4740
- [
4741
- "get",
4742
- "/api/agents",
4743
- agents.listAgents
4744
- ],
4745
- [
4746
- "post",
4747
- "/api/agents",
4748
- agents.createAgent
4749
- ],
4750
- [
4751
- "put",
4752
- "/api/agents/:agentId",
4753
- agents.updateAgent
4754
- ],
4755
- [
4756
- "delete",
4757
- "/api/agents/:agentId",
4758
- agents.deleteAgent
4759
- ],
4760
- [
4761
- "get",
4762
- "/api/agents/:agentId/avatar",
4763
- agents.getAgentAvatar
4764
- ]
4765
- ]);
4766
- this.mountRoutes([
4767
- [
4768
- "get",
4769
- "/api/config",
4770
- config.getConfig
4771
- ],
4772
- [
4773
- "get",
4774
- "/api/config/meta",
4775
- config.getConfigMeta
4776
- ],
4777
- [
4778
- "get",
4779
- "/api/config/schema",
4780
- config.getConfigSchema
4781
- ],
4782
- [
4783
- "put",
4784
- "/api/config/model",
4785
- config.updateConfigModel
4786
- ],
4787
- [
4788
- "put",
4789
- "/api/config/search",
4790
- config.updateConfigSearch
4791
- ],
4792
- [
4793
- "put",
4794
- "/api/config/providers/:provider",
4795
- config.updateProvider
4796
- ],
4797
- [
4798
- "post",
4799
- "/api/config/providers",
4800
- config.createProvider
4801
- ],
4802
- [
4803
- "delete",
4804
- "/api/config/providers/:provider",
4805
- config.deleteProvider
4806
- ],
4807
- [
4808
- "post",
4809
- "/api/config/providers/:provider/test",
4810
- config.testProviderConnection
4811
- ],
4812
- [
4813
- "post",
4814
- "/api/config/providers/:provider/auth/start",
4815
- config.startProviderAuth
4816
- ],
4817
- [
4818
- "post",
4819
- "/api/config/providers/:provider/auth/poll",
4820
- config.pollProviderAuth
4821
- ],
4822
- [
4823
- "post",
4824
- "/api/config/providers/:provider/auth/import-cli",
4825
- config.importProviderAuthFromCli
4826
- ],
4827
- [
4828
- "put",
4829
- "/api/config/channels/:channel",
4830
- config.updateChannel
4831
- ],
4832
- [
4833
- "post",
4834
- "/api/config/channels/:channel/auth/start",
4835
- config.startChannelAuth
4836
- ],
4837
- [
4838
- "post",
4839
- "/api/config/channels/:channel/auth/connect",
4840
- config.connectChannelAuth
4841
- ],
4842
- [
4843
- "post",
4844
- "/api/config/channels/:channel/auth/poll",
4845
- config.pollChannelAuth
4846
- ],
4847
- [
4848
- "put",
4849
- "/api/config/secrets",
4850
- config.updateSecrets
4851
- ],
4852
- [
4853
- "put",
4854
- "/api/config/runtime",
4855
- config.updateRuntime
4856
- ],
4857
- [
4858
- "post",
4859
- "/api/config/actions/:actionId/execute",
4860
- config.executeAction
4861
- ]
4862
- ]);
4763
+ mountResourceRoutes = () => {
4764
+ const { ncpSession, panelApps, serviceApps, serverPath } = this.controllers;
4863
4765
  this.mountRoutes([
4864
4766
  [
4865
4767
  "get",
@@ -4981,6 +4883,11 @@ var UiRouteRegistry = class {
4981
4883
  "/api/service-apps/:appId",
4982
4884
  serviceApps.getServiceApp
4983
4885
  ],
4886
+ [
4887
+ "delete",
4888
+ "/api/service-apps/:appId",
4889
+ serviceApps.deleteServiceApp
4890
+ ],
4984
4891
  [
4985
4892
  "get",
4986
4893
  "/api/service-actions",
@@ -5022,6 +4929,194 @@ var UiRouteRegistry = class {
5022
4929
  serverPath.read
5023
4930
  ]
5024
4931
  ]);
4932
+ };
4933
+ register = () => {
4934
+ const { agents, app, auth, config, cron, ncpAsset, remote, runtimeControl, runtimeUpdate } = this.controllers;
4935
+ this.mountRoutes([
4936
+ [
4937
+ "get",
4938
+ "/api/health",
4939
+ app.health
4940
+ ],
4941
+ [
4942
+ "get",
4943
+ "/api/app/meta",
4944
+ app.appMeta
4945
+ ],
4946
+ [
4947
+ "get",
4948
+ "/api/runtime/bootstrap-status",
4949
+ app.bootstrapStatus
4950
+ ],
4951
+ [
4952
+ "get",
4953
+ "/api/auth/status",
4954
+ auth.getStatus
4955
+ ],
4956
+ [
4957
+ "post",
4958
+ "/api/auth/setup",
4959
+ auth.setup
4960
+ ],
4961
+ [
4962
+ "post",
4963
+ "/api/auth/login",
4964
+ auth.login
4965
+ ],
4966
+ [
4967
+ "post",
4968
+ "/api/auth/logout",
4969
+ auth.logout
4970
+ ],
4971
+ [
4972
+ "put",
4973
+ "/api/auth/password",
4974
+ auth.updatePassword
4975
+ ],
4976
+ [
4977
+ "put",
4978
+ "/api/auth/enabled",
4979
+ auth.updateEnabled
4980
+ ],
4981
+ [
4982
+ "post",
4983
+ "/api/auth/bridge",
4984
+ auth.issueBridgeSession
4985
+ ],
4986
+ [
4987
+ "get",
4988
+ "/api/agents",
4989
+ agents.listAgents
4990
+ ],
4991
+ [
4992
+ "post",
4993
+ "/api/agents",
4994
+ agents.createAgent
4995
+ ],
4996
+ [
4997
+ "put",
4998
+ "/api/agents/:agentId",
4999
+ agents.updateAgent
5000
+ ],
5001
+ [
5002
+ "delete",
5003
+ "/api/agents/:agentId",
5004
+ agents.deleteAgent
5005
+ ],
5006
+ [
5007
+ "get",
5008
+ "/api/agents/:agentId/avatar",
5009
+ agents.getAgentAvatar
5010
+ ]
5011
+ ]);
5012
+ this.mountRoutes([
5013
+ [
5014
+ "get",
5015
+ "/api/config",
5016
+ config.getConfig
5017
+ ],
5018
+ [
5019
+ "get",
5020
+ "/api/config/meta",
5021
+ config.getConfigMeta
5022
+ ],
5023
+ [
5024
+ "get",
5025
+ "/api/config/schema",
5026
+ config.getConfigSchema
5027
+ ],
5028
+ [
5029
+ "get",
5030
+ "/api/providers",
5031
+ config.listProviders
5032
+ ],
5033
+ [
5034
+ "get",
5035
+ "/api/provider-templates",
5036
+ config.listProviderTemplates
5037
+ ],
5038
+ [
5039
+ "post",
5040
+ "/api/providers",
5041
+ config.createProvider
5042
+ ],
5043
+ [
5044
+ "put",
5045
+ "/api/providers/:providerId",
5046
+ config.updateProvider
5047
+ ],
5048
+ [
5049
+ "delete",
5050
+ "/api/providers/:providerId",
5051
+ config.deleteProvider
5052
+ ],
5053
+ [
5054
+ "post",
5055
+ "/api/providers/:providerId/test",
5056
+ config.testProviderConnection
5057
+ ],
5058
+ [
5059
+ "post",
5060
+ "/api/providers/:providerId/auth/start",
5061
+ config.startProviderAuth
5062
+ ],
5063
+ [
5064
+ "post",
5065
+ "/api/providers/:providerId/auth/poll",
5066
+ config.pollProviderAuth
5067
+ ],
5068
+ [
5069
+ "post",
5070
+ "/api/providers/:providerId/auth/import-cli",
5071
+ config.importProviderAuthFromCli
5072
+ ],
5073
+ [
5074
+ "put",
5075
+ "/api/config/model",
5076
+ config.updateConfigModel
5077
+ ],
5078
+ [
5079
+ "put",
5080
+ "/api/config/search",
5081
+ config.updateConfigSearch
5082
+ ],
5083
+ [
5084
+ "put",
5085
+ "/api/config/channels/:channel",
5086
+ config.updateChannel
5087
+ ],
5088
+ [
5089
+ "post",
5090
+ "/api/config/channels/:channel/auth/start",
5091
+ config.startChannelAuth
5092
+ ],
5093
+ [
5094
+ "post",
5095
+ "/api/config/channels/:channel/auth/connect",
5096
+ config.connectChannelAuth
5097
+ ],
5098
+ [
5099
+ "post",
5100
+ "/api/config/channels/:channel/auth/poll",
5101
+ config.pollChannelAuth
5102
+ ],
5103
+ [
5104
+ "put",
5105
+ "/api/config/secrets",
5106
+ config.updateSecrets
5107
+ ],
5108
+ [
5109
+ "put",
5110
+ "/api/config/runtime",
5111
+ config.updateRuntime
5112
+ ],
5113
+ [
5114
+ "post",
5115
+ "/api/config/actions/:actionId/execute",
5116
+ config.executeAction
5117
+ ]
5118
+ ]);
5119
+ this.mountResourceRoutes();
5025
5120
  this.mountNcpAgentRoutes(this.options.kernel, ncpAsset);
5026
5121
  this.mountRoutes([
5027
5122
  [
@@ -5338,6 +5433,6 @@ async function startUiServer(gateway) {
5338
5433
  };
5339
5434
  }
5340
5435
  //#endregion
5341
- export { ConfigRoutesController, PanelAppsRoutesController, RuntimeControlRoutesController, ServiceAppsRoutesController, buildConfigMeta, buildConfigSchemaView, buildConfigView, createCustomProvider, createUiRouter, deleteCustomProvider, ensureUiBridgeSecret, executeConfigAction, getUiBridgeSecretPath, loadConfigOrDefault, readUiBridgeSecret, startUiServer, testProviderConnection, updateChannel, updateModel, updateProvider, updateRuntime, updateSearch, updateSecrets };
5436
+ export { ConfigRoutesController, PanelAppsRoutesController, RuntimeControlRoutesController, ServiceAppsRoutesController, buildConfigMeta, buildConfigSchemaView, buildConfigView, buildProviderTemplatesView, buildProvidersView, createProvider, createUiRouter, deleteProvider, ensureUiBridgeSecret, executeConfigAction, getUiBridgeSecretPath, loadConfigOrDefault, readUiBridgeSecret, startUiServer, testProviderConnection, updateChannel, updateModel, updateProvider, updateRuntime, updateSearch, updateSecrets };
5342
5437
 
5343
5438
  //# sourceMappingURL=index.js.map