agent-nuvira 3.3.19 → 3.5.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/agent-sdk/src/register.d.ts +23 -7
- package/dist/agent-sdk/src/register.d.ts.map +1 -1
- package/dist/agent-sdk/src/register.js +159 -5
- package/dist/agent-sdk/src/register.js.map +1 -1
- package/dist/agent-sdk/src/scaffold.d.ts +1 -1
- package/dist/agent-sdk/src/scaffold.js +1 -1
- package/dist/cli/agent.d.ts.map +1 -1
- package/dist/cli/agent.js +16 -3
- package/dist/cli/agent.js.map +1 -1
- package/dist/cli/chat.d.ts +85 -0
- package/dist/cli/chat.d.ts.map +1 -1
- package/dist/cli/chat.js +462 -15
- package/dist/cli/chat.js.map +1 -1
- package/dist/cli/config.d.ts +10 -0
- package/dist/cli/config.d.ts.map +1 -1
- package/dist/cli/config.js +39 -0
- package/dist/cli/config.js.map +1 -1
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +18 -3
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/mcp.d.ts +50 -0
- package/dist/cli/mcp.d.ts.map +1 -1
- package/dist/cli/mcp.js +496 -49
- package/dist/cli/mcp.js.map +1 -1
- package/dist/cli/memory.d.ts.map +1 -1
- package/dist/cli/memory.js +3 -2
- package/dist/cli/memory.js.map +1 -1
- package/dist/cli/plugins.d.ts.map +1 -1
- package/dist/cli/plugins.js +26 -9
- package/dist/cli/plugins.js.map +1 -1
- package/dist/cli/sdk.d.ts.map +1 -1
- package/dist/cli/sdk.js +10 -3
- package/dist/cli/sdk.js.map +1 -1
- package/dist/cli/tool-install-prompt.d.ts.map +1 -1
- package/dist/cli/tool-install-prompt.js +23 -1
- package/dist/cli/tool-install-prompt.js.map +1 -1
- package/dist/cli/tools.d.ts +16 -0
- package/dist/cli/tools.d.ts.map +1 -1
- package/dist/cli/tools.js +101 -1
- package/dist/cli/tools.js.map +1 -1
- package/dist/config/manager.d.ts +6 -0
- package/dist/config/manager.d.ts.map +1 -1
- package/dist/config/manager.js +66 -0
- package/dist/config/manager.js.map +1 -1
- package/dist/config/types.d.ts +18 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/learning/exhaustion-report.d.ts +12 -0
- package/dist/learning/exhaustion-report.d.ts.map +1 -1
- package/dist/learning/exhaustion-report.js +3 -1
- package/dist/learning/exhaustion-report.js.map +1 -1
- package/dist/learning/model-capability.d.ts +33 -0
- package/dist/learning/model-capability.d.ts.map +1 -1
- package/dist/learning/model-capability.js +51 -0
- package/dist/learning/model-capability.js.map +1 -1
- package/dist/learning/model-first-router.d.ts +7 -22
- package/dist/learning/model-first-router.d.ts.map +1 -1
- package/dist/learning/model-first-router.js +7 -37
- package/dist/learning/model-first-router.js.map +1 -1
- package/dist/learning/model-selection.d.ts +27 -0
- package/dist/learning/model-selection.d.ts.map +1 -1
- package/dist/learning/model-selection.js +46 -0
- package/dist/learning/model-selection.js.map +1 -1
- package/dist/learning/reasoning-trace.d.ts +1 -1
- package/dist/learning/reasoning-trace.d.ts.map +1 -1
- package/dist/learning/reasoning-trace.js.map +1 -1
- package/dist/learning/resilient-call.d.ts +15 -1
- package/dist/learning/resilient-call.d.ts.map +1 -1
- package/dist/learning/resilient-call.js +38 -22
- package/dist/learning/resilient-call.js.map +1 -1
- package/dist/learning/working-state.d.ts +7 -0
- package/dist/learning/working-state.d.ts.map +1 -1
- package/dist/learning/working-state.js +23 -1
- package/dist/learning/working-state.js.map +1 -1
- package/dist/mcp/catalog.d.ts +206 -26
- package/dist/mcp/catalog.d.ts.map +1 -1
- package/dist/mcp/catalog.js +664 -52
- package/dist/mcp/catalog.js.map +1 -1
- package/dist/mcp/client.d.ts +6 -0
- package/dist/mcp/client.d.ts.map +1 -1
- package/dist/mcp/client.js +35 -5
- package/dist/mcp/client.js.map +1 -1
- package/dist/mcp/custom-server.d.ts +120 -0
- package/dist/mcp/custom-server.d.ts.map +1 -0
- package/dist/mcp/custom-server.js +330 -0
- package/dist/mcp/custom-server.js.map +1 -0
- package/dist/mcp/manager.d.ts +9 -1
- package/dist/mcp/manager.d.ts.map +1 -1
- package/dist/mcp/manager.js +15 -2
- package/dist/mcp/manager.js.map +1 -1
- package/dist/mcp/mcp-oauth.d.ts +28 -0
- package/dist/mcp/mcp-oauth.d.ts.map +1 -1
- package/dist/mcp/mcp-oauth.js +63 -8
- package/dist/mcp/mcp-oauth.js.map +1 -1
- package/dist/mcp/oauth-authorize.d.ts +51 -0
- package/dist/mcp/oauth-authorize.d.ts.map +1 -0
- package/dist/mcp/oauth-authorize.js +133 -0
- package/dist/mcp/oauth-authorize.js.map +1 -0
- package/dist/mcp/oauth-connect.d.ts +53 -0
- package/dist/mcp/oauth-connect.d.ts.map +1 -0
- package/dist/mcp/oauth-connect.js +103 -0
- package/dist/mcp/oauth-connect.js.map +1 -0
- package/dist/mcp/pin-verifier.d.ts +44 -0
- package/dist/mcp/pin-verifier.d.ts.map +1 -0
- package/dist/mcp/pin-verifier.js +102 -0
- package/dist/mcp/pin-verifier.js.map +1 -0
- package/dist/mcp/prereqs.d.ts +145 -0
- package/dist/mcp/prereqs.d.ts.map +1 -0
- package/dist/mcp/prereqs.js +245 -0
- package/dist/mcp/prereqs.js.map +1 -0
- package/dist/mcp/runtime.d.ts +59 -0
- package/dist/mcp/runtime.d.ts.map +1 -0
- package/dist/mcp/runtime.js +77 -0
- package/dist/mcp/runtime.js.map +1 -0
- package/dist/mcp/server.d.ts +21 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +29 -1
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/settings.d.ts +164 -0
- package/dist/mcp/settings.d.ts.map +1 -0
- package/dist/mcp/settings.js +358 -0
- package/dist/mcp/settings.js.map +1 -0
- package/dist/mcp/types.d.ts +62 -0
- package/dist/mcp/types.d.ts.map +1 -1
- package/dist/mcp/types.js.map +1 -1
- package/dist/memory/vector-store.d.ts +12 -0
- package/dist/memory/vector-store.d.ts.map +1 -1
- package/dist/memory/vector-store.js +23 -0
- package/dist/memory/vector-store.js.map +1 -1
- package/dist/plugins/agent-plugin.d.ts +35 -0
- package/dist/plugins/agent-plugin.d.ts.map +1 -1
- package/dist/plugins/agent-plugin.js +142 -24
- package/dist/plugins/agent-plugin.js.map +1 -1
- package/dist/sandbox/manager.d.ts +12 -0
- package/dist/sandbox/manager.d.ts.map +1 -1
- package/dist/sandbox/manager.js +43 -2
- package/dist/sandbox/manager.js.map +1 -1
- package/dist/tools/modality/browser.d.ts +39 -3
- package/dist/tools/modality/browser.d.ts.map +1 -1
- package/dist/tools/modality/browser.js +113 -16
- package/dist/tools/modality/browser.js.map +1 -1
- package/dist/tools/optional-deps.d.ts +48 -0
- package/dist/tools/optional-deps.d.ts.map +1 -0
- package/dist/tools/optional-deps.js +42 -0
- package/dist/tools/optional-deps.js.map +1 -0
- package/dist/tools/registry.d.ts.map +1 -1
- package/dist/tools/registry.js +68 -11
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/remediation-ladder.d.ts.map +1 -1
- package/dist/tools/remediation-ladder.js +9 -1
- package/dist/tools/remediation-ladder.js.map +1 -1
- package/dist/tools/tool-loop.d.ts.map +1 -1
- package/dist/tools/tool-loop.js +57 -5
- package/dist/tools/tool-loop.js.map +1 -1
- package/dist/web-dashboard/chat-retry.d.ts +11 -1
- package/dist/web-dashboard/chat-retry.d.ts.map +1 -1
- package/dist/web-dashboard/chat-retry.js +18 -4
- package/dist/web-dashboard/chat-retry.js.map +1 -1
- package/dist/web-dashboard/server.d.ts.map +1 -1
- package/dist/web-dashboard/server.js +349 -2
- package/dist/web-dashboard/server.js.map +1 -1
- package/package.json +3 -2
- package/src/web-dashboard/public/assets/index-aO3aG7ex.css +1 -0
- package/src/web-dashboard/public/assets/{index-Bz7QqQ_N.js → index-yky0dw5e.js} +115 -89
- package/src/web-dashboard/public/assets/index-yky0dw5e.js.map +1 -0
- package/src/web-dashboard/public/index.html +2 -2
- package/src/web-dashboard/public/assets/index-Bz7QqQ_N.js.map +0 -1
- package/src/web-dashboard/public/assets/index-cBWT2qxn.css +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/web-dashboard/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,YAAY,EAAmC,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/web-dashboard/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -23,6 +23,7 @@ import { resolveBuffConfigDir, resolveBuffConfigPath, resolveNuviraHome } from '
|
|
|
23
23
|
import { createRequire } from 'node:module';
|
|
24
24
|
import { loadEnv } from '../utils/env.js';
|
|
25
25
|
import { ConfigManager } from '../config/manager.js';
|
|
26
|
+
import { parseRuntimeSpec } from '../mcp/runtime.js';
|
|
26
27
|
import { runAllChecks } from '../cli/doctor.js';
|
|
27
28
|
import { getAutoRouter } from '../learning/auto-router.js';
|
|
28
29
|
import { acceptanceSummary, collectLabelledTurns, serializeLabelledTurns, parseCorpusText, detectCorpusFormat, mergeImportedLabels, } from '../learning/acceptance-model.js';
|
|
@@ -34,7 +35,7 @@ import { getRouterPromotion } from '../learning/router-promotion.js';
|
|
|
34
35
|
import { AUTH_CLEAR_THRESHOLD } from '../learning/key-hygiene.js';
|
|
35
36
|
import { ACTION_LOG_FILENAME, DEFAULT_STALE_MS, aggregateActionTelemetry, readActionTelemetryFile, getModelRegistry, } from '../learning/model-registry.js';
|
|
36
37
|
import { classifyModelEntitlement } from '../inference/model-entitlement.js';
|
|
37
|
-
import { capabilityBand, estimateModelCapability } from '../learning/model-capability.js';
|
|
38
|
+
import { capabilityBand, estimateModelCapability, capabilityClassOf, bandRank } from '../learning/model-capability.js';
|
|
38
39
|
import { listUnattendedJobs } from '../learning/unattended-job.js';
|
|
39
40
|
import { AdminSessions, countAdminRoleUsers, isAdminConfigured, listAdminUsers, mustChangePasswordFor, removeAdminUser, roleForUser, verifyAdmin, writeAdminUser, MIN_ADMIN_PASSWORD_LENGTH, } from './src/admin-auth.js';
|
|
40
41
|
import { TaskRunner } from './task-runner.js';
|
|
@@ -3614,6 +3615,323 @@ function handleRequest(req, res) {
|
|
|
3614
3615
|
})();
|
|
3615
3616
|
return;
|
|
3616
3617
|
}
|
|
3618
|
+
// ── MCP configuration (2026-10-12) ─────────────────────────────────────
|
|
3619
|
+
//
|
|
3620
|
+
// ONE SOURCE OF TRUTH. These routes write the SAME `mcp.*` section of
|
|
3621
|
+
// `buffconfig.json` that `nuvira config set mcp.*` writes, through the same
|
|
3622
|
+
// parser (`parseMcpSetting` / `mergeMcpSetting`) and the same install path
|
|
3623
|
+
// (`installCatalogServer` + pin verification). A dashboard key cannot be
|
|
3624
|
+
// accepted here and rejected there, and neither surface can develop its own
|
|
3625
|
+
// idea of what a cap or a runtime override means.
|
|
3626
|
+
//
|
|
3627
|
+
// Secrets: the env VALUES a user types are written to the server's own config
|
|
3628
|
+
// file (0600 when it carries one) and are never echoed back — the read route
|
|
3629
|
+
// returns env KEY NAMES only, so a token cannot leak into the page or a log.
|
|
3630
|
+
if (pathname === '/api/mcp' && req.method === 'GET') {
|
|
3631
|
+
void (async () => {
|
|
3632
|
+
const session = adminSessions.validate(bearerToken(req));
|
|
3633
|
+
if (!session) {
|
|
3634
|
+
writeJson(res, 401, { ok: false, error: 'Not authenticated — log in first.' });
|
|
3635
|
+
return;
|
|
3636
|
+
}
|
|
3637
|
+
// `?deep=1` runs the service checks (e.g. `docker info`); a plain page load
|
|
3638
|
+
// stays cheap and says which checks it skipped.
|
|
3639
|
+
const deep = new URL(req.url ?? '', 'http://localhost').searchParams.get('deep') === '1';
|
|
3640
|
+
const [{ loadMcpSettings }, { getMCPManager }, catalog, { resolveMcpConfigDir }] = await Promise.all([
|
|
3641
|
+
import('../mcp/settings.js'),
|
|
3642
|
+
import('../mcp/manager.js'),
|
|
3643
|
+
import('../mcp/catalog.js'),
|
|
3644
|
+
import('../config/paths.js'),
|
|
3645
|
+
]);
|
|
3646
|
+
const { evaluateVariants, effectiveProbeEnv, isCatalogServerInstalled } = catalog;
|
|
3647
|
+
const { describePrereqProblems } = await import('../mcp/prereqs.js');
|
|
3648
|
+
const manager = getMCPManager();
|
|
3649
|
+
const configs = manager.discoverConfigs();
|
|
3650
|
+
const states = manager.getAllStates();
|
|
3651
|
+
const servers = configs.map((config) => {
|
|
3652
|
+
const state = states.find((s) => s.name === config.name);
|
|
3653
|
+
return {
|
|
3654
|
+
name: config.name,
|
|
3655
|
+
transport: config.transport,
|
|
3656
|
+
enabled: config.enabled !== false,
|
|
3657
|
+
variant: config.variant ?? null,
|
|
3658
|
+
command: config.command ?? null,
|
|
3659
|
+
args: config.args ?? [],
|
|
3660
|
+
url: config.url ?? null,
|
|
3661
|
+
runtime: config.runtime ?? null,
|
|
3662
|
+
// KEY NAMES only — never the values.
|
|
3663
|
+
envKeys: Object.keys(config.env ?? {}),
|
|
3664
|
+
headerKeys: Object.keys(config.headers ?? {}),
|
|
3665
|
+
// A curated install and a hand-written file are both legitimate; the
|
|
3666
|
+
// label lets the page offer "edit" only for the editable kind.
|
|
3667
|
+
origin: config.variant || catalog.getCatalogEntry(config.name) ? 'catalog' : 'custom',
|
|
3668
|
+
connected: state?.status === 'connected',
|
|
3669
|
+
toolCount: state?.tools.length ?? 0,
|
|
3670
|
+
};
|
|
3671
|
+
});
|
|
3672
|
+
const probe = { deep, env: effectiveProbeEnv() };
|
|
3673
|
+
const catalogEntries = catalog.MCP_CATALOG.map((entry) => ({
|
|
3674
|
+
name: entry.name,
|
|
3675
|
+
description: entry.description,
|
|
3676
|
+
offers: entry.offers,
|
|
3677
|
+
supersedes: entry.supersedes ?? null,
|
|
3678
|
+
installed: isCatalogServerInstalled(entry.name),
|
|
3679
|
+
variants: evaluateVariants(entry, { probe }).map(({ variant, status }) => ({
|
|
3680
|
+
id: variant.id,
|
|
3681
|
+
label: variant.label,
|
|
3682
|
+
transport: variant.transport,
|
|
3683
|
+
command: variant.command ?? null,
|
|
3684
|
+
args: variant.args ?? [],
|
|
3685
|
+
url: variant.url ?? null,
|
|
3686
|
+
trust: variant.trust,
|
|
3687
|
+
optIn: variant.optIn === true,
|
|
3688
|
+
note: variant.note ?? null,
|
|
3689
|
+
requires: variant.requires.map((r) => ({
|
|
3690
|
+
kind: r.kind,
|
|
3691
|
+
name: r.name,
|
|
3692
|
+
minVersion: r.minVersion ?? null,
|
|
3693
|
+
hint: r.hint,
|
|
3694
|
+
})),
|
|
3695
|
+
status: {
|
|
3696
|
+
ok: status.ok,
|
|
3697
|
+
problems: describePrereqProblems(status),
|
|
3698
|
+
unverified: status.unverified,
|
|
3699
|
+
// A service prerequisite is only established in deep mode — say so
|
|
3700
|
+
// rather than implying the daemon was checked.
|
|
3701
|
+
needsDeep: !deep && variant.requires.some((r) => r.kind === 'service'),
|
|
3702
|
+
},
|
|
3703
|
+
})),
|
|
3704
|
+
}));
|
|
3705
|
+
writeJson(res, 200, {
|
|
3706
|
+
ok: true,
|
|
3707
|
+
canWrite: roleCan(session.role, 'routing.operate'),
|
|
3708
|
+
configDir: resolveMcpConfigDir(),
|
|
3709
|
+
deep,
|
|
3710
|
+
settings: loadMcpSettings(),
|
|
3711
|
+
servers,
|
|
3712
|
+
catalog: catalogEntries,
|
|
3713
|
+
});
|
|
3714
|
+
})();
|
|
3715
|
+
return;
|
|
3716
|
+
}
|
|
3717
|
+
// POST /api/mcp/settings — write `mcp.*` values (same keys as the CLI).
|
|
3718
|
+
if (pathname === '/api/mcp/settings' && req.method === 'POST') {
|
|
3719
|
+
void (async () => {
|
|
3720
|
+
const session = adminSessions.validate(bearerToken(req));
|
|
3721
|
+
if (!session) {
|
|
3722
|
+
writeJson(res, 401, { ok: false, error: 'Not authenticated — log in first.' });
|
|
3723
|
+
return;
|
|
3724
|
+
}
|
|
3725
|
+
if (!roleCan(session.role, 'routing.operate')) {
|
|
3726
|
+
writeJson(res, 403, {
|
|
3727
|
+
ok: false,
|
|
3728
|
+
error: `Access denied — role '${session.role}' cannot change MCP configuration (requires admin or operator).`,
|
|
3729
|
+
});
|
|
3730
|
+
return;
|
|
3731
|
+
}
|
|
3732
|
+
const body = await readJsonBody(req);
|
|
3733
|
+
const patch = Array.isArray(body?.patch) ? body.patch : null;
|
|
3734
|
+
if (!patch || patch.length === 0) {
|
|
3735
|
+
writeJson(res, 400, {
|
|
3736
|
+
ok: false,
|
|
3737
|
+
error: 'Expected { patch: [{ key: "mcp.maxToolsTotal", value: "40" }, …] }.',
|
|
3738
|
+
});
|
|
3739
|
+
return;
|
|
3740
|
+
}
|
|
3741
|
+
const { parseMcpSetting, mergeMcpSetting, loadMcpSettings } = await import('../mcp/settings.js');
|
|
3742
|
+
const configManager = new ConfigManager();
|
|
3743
|
+
let merged = configManager.getAll().mcp ?? {};
|
|
3744
|
+
const errors = [];
|
|
3745
|
+
for (const item of patch) {
|
|
3746
|
+
if (typeof item?.key !== 'string') {
|
|
3747
|
+
errors.push('Every patch entry needs a string `key`.');
|
|
3748
|
+
continue;
|
|
3749
|
+
}
|
|
3750
|
+
const parsed = parseMcpSetting(item.key, item.value === undefined ? '' : String(item.value));
|
|
3751
|
+
if (!parsed.ok)
|
|
3752
|
+
errors.push(parsed.error);
|
|
3753
|
+
else
|
|
3754
|
+
merged = mergeMcpSetting(merged, parsed.mcp);
|
|
3755
|
+
}
|
|
3756
|
+
if (errors.length > 0) {
|
|
3757
|
+
writeJson(res, 400, { ok: false, error: errors.join('\n') });
|
|
3758
|
+
return;
|
|
3759
|
+
}
|
|
3760
|
+
configManager.save({ mcp: merged });
|
|
3761
|
+
writeJson(res, 200, { ok: true, settings: loadMcpSettings() });
|
|
3762
|
+
})();
|
|
3763
|
+
return;
|
|
3764
|
+
}
|
|
3765
|
+
// POST /api/mcp/install — install a catalog capability through the same
|
|
3766
|
+
// gates the CLI uses (prerequisites probed, pin verified, refuse loudly).
|
|
3767
|
+
if (pathname === '/api/mcp/install' && req.method === 'POST') {
|
|
3768
|
+
void (async () => {
|
|
3769
|
+
const session = adminSessions.validate(bearerToken(req));
|
|
3770
|
+
if (!session) {
|
|
3771
|
+
writeJson(res, 401, { ok: false, error: 'Not authenticated — log in first.' });
|
|
3772
|
+
return;
|
|
3773
|
+
}
|
|
3774
|
+
if (!roleCan(session.role, 'routing.operate')) {
|
|
3775
|
+
writeJson(res, 403, {
|
|
3776
|
+
ok: false,
|
|
3777
|
+
error: `Access denied — role '${session.role}' cannot install MCP servers (requires admin or operator).`,
|
|
3778
|
+
});
|
|
3779
|
+
return;
|
|
3780
|
+
}
|
|
3781
|
+
const body = await readJsonBody(req);
|
|
3782
|
+
const name = typeof body?.name === 'string' ? body.name.trim() : '';
|
|
3783
|
+
const catalog = await import('../mcp/catalog.js');
|
|
3784
|
+
const entry = catalog.getCatalogEntry(name);
|
|
3785
|
+
if (!entry) {
|
|
3786
|
+
writeJson(res, 400, { ok: false, error: `'${name}' is not in the catalog.` });
|
|
3787
|
+
return;
|
|
3788
|
+
}
|
|
3789
|
+
const variantId = typeof body?.variant === 'string' && body.variant.trim() ? body.variant.trim() : undefined;
|
|
3790
|
+
const runtime = parseRuntimeSpec(typeof body?.runtime === 'string' ? body.runtime : undefined);
|
|
3791
|
+
const command = typeof body?.command === 'string' && body.command.trim() ? body.command.trim() : undefined;
|
|
3792
|
+
const force = body?.force === true;
|
|
3793
|
+
const env = {};
|
|
3794
|
+
if (body?.env && typeof body.env === 'object') {
|
|
3795
|
+
for (const [k, v] of Object.entries(body.env)) {
|
|
3796
|
+
if (typeof v === 'string' && v.trim())
|
|
3797
|
+
env[k] = v;
|
|
3798
|
+
}
|
|
3799
|
+
}
|
|
3800
|
+
const { verifyNpmSpec } = await import('../mcp/pin-verifier.js');
|
|
3801
|
+
const probeEnv = catalog.effectiveProbeEnv(undefined, env);
|
|
3802
|
+
const chosen = catalog.chooseVariant(entry, {
|
|
3803
|
+
...(variantId ? { variantId } : {}),
|
|
3804
|
+
...(runtime ? { runtime } : {}),
|
|
3805
|
+
probe: { env: probeEnv, deep: true },
|
|
3806
|
+
});
|
|
3807
|
+
const variant = chosen.ok
|
|
3808
|
+
? chosen.choice.variant
|
|
3809
|
+
: variantId
|
|
3810
|
+
? chosen.choices.find((c) => c.variant.id === variantId)?.variant
|
|
3811
|
+
: undefined;
|
|
3812
|
+
// Registry check (network, bounded) before anything is written.
|
|
3813
|
+
let pinVerdict;
|
|
3814
|
+
const specs = variant ? catalog.npmSpecsForVariant(variant) : [];
|
|
3815
|
+
if (specs.length > 0) {
|
|
3816
|
+
const verdicts = await Promise.all(specs.map((spec) => verifyNpmSpec(spec)));
|
|
3817
|
+
pinVerdict = verdicts.find((v) => v.checked && !v.ok) ?? verdicts.find((v) => !v.checked) ?? { checked: true, ok: true };
|
|
3818
|
+
}
|
|
3819
|
+
const result = catalog.installCatalogServer(entry, env, undefined, {
|
|
3820
|
+
...(variantId ? { variantId } : {}),
|
|
3821
|
+
...(command ? { command } : {}),
|
|
3822
|
+
...(runtime ? { runtime } : {}),
|
|
3823
|
+
...(pinVerdict ? { pinVerdict: pinVerdict } : {}),
|
|
3824
|
+
...(force ? { force: true } : {}),
|
|
3825
|
+
probe: { env: probeEnv, deep: true },
|
|
3826
|
+
});
|
|
3827
|
+
// The written path is returned; secret VALUES never are.
|
|
3828
|
+
writeJson(res, result.ok ? 200 : 400, {
|
|
3829
|
+
ok: result.ok,
|
|
3830
|
+
reason: result.reason,
|
|
3831
|
+
variantId: result.variantId,
|
|
3832
|
+
path: result.path,
|
|
3833
|
+
missing: result.missing,
|
|
3834
|
+
unverifiedPins: result.unverifiedPins,
|
|
3835
|
+
});
|
|
3836
|
+
})();
|
|
3837
|
+
return;
|
|
3838
|
+
}
|
|
3839
|
+
// POST /api/mcp/servers — CREATE or REPLACE a server by hand.
|
|
3840
|
+
//
|
|
3841
|
+
// The Claude-Desktop-parity path: the catalog is a convenience, not a gate, so
|
|
3842
|
+
// the dashboard can configure ANY MCP server by name — a stdio command this
|
|
3843
|
+
// project has never heard of, or a remote endpoint with its own headers. It
|
|
3844
|
+
// goes through the SAME validator/writer the CLI's `mcp add` uses, so a config
|
|
3845
|
+
// accepted in one surface cannot be refused in the other, and like every other
|
|
3846
|
+
// MCP write it rides the `routing.operate` capability (admin or operator).
|
|
3847
|
+
//
|
|
3848
|
+
// Secrets: values arrive here and go to a 0600 config file; the response
|
|
3849
|
+
// reports the path and env KEY NAMES, never a value.
|
|
3850
|
+
if (pathname === '/api/mcp/servers' && req.method === 'POST') {
|
|
3851
|
+
void (async () => {
|
|
3852
|
+
const session = adminSessions.validate(bearerToken(req));
|
|
3853
|
+
if (!session) {
|
|
3854
|
+
writeJson(res, 401, { ok: false, error: 'Not authenticated — log in first.' });
|
|
3855
|
+
return;
|
|
3856
|
+
}
|
|
3857
|
+
if (!roleCan(session.role, 'routing.operate')) {
|
|
3858
|
+
writeJson(res, 403, {
|
|
3859
|
+
ok: false,
|
|
3860
|
+
error: `Access denied — role '${session.role}' cannot configure MCP servers (requires admin or operator).`,
|
|
3861
|
+
});
|
|
3862
|
+
return;
|
|
3863
|
+
}
|
|
3864
|
+
const body = await readJsonBody(req);
|
|
3865
|
+
const { validateServerSpec, writeServerConfig } = await import('../mcp/custom-server.js');
|
|
3866
|
+
// Blank values are dropped, not written: the edit form cannot show an
|
|
3867
|
+
// existing secret (the API never returns values), so it submits the KEY
|
|
3868
|
+
// with an empty value — which must mean "unchanged", never "erase".
|
|
3869
|
+
const collect = (input) => {
|
|
3870
|
+
if (!input || typeof input !== 'object' || Array.isArray(input))
|
|
3871
|
+
return {};
|
|
3872
|
+
const out = {};
|
|
3873
|
+
for (const [k, v] of Object.entries(input)) {
|
|
3874
|
+
if (typeof v === 'string' && v.trim())
|
|
3875
|
+
out[k] = v;
|
|
3876
|
+
}
|
|
3877
|
+
return out;
|
|
3878
|
+
};
|
|
3879
|
+
const validated = validateServerSpec({
|
|
3880
|
+
name: typeof body?.name === 'string' ? body.name : '',
|
|
3881
|
+
...(typeof body?.transport === 'string' ? { transport: body.transport } : {}),
|
|
3882
|
+
...(typeof body?.command === 'string' && body.command.trim() ? { command: body.command } : {}),
|
|
3883
|
+
...(Array.isArray(body?.args) ? { args: body.args.filter((a) => typeof a === 'string') } : {}),
|
|
3884
|
+
...(typeof body?.url === 'string' && body.url.trim() ? { url: body.url } : {}),
|
|
3885
|
+
env: collect(body?.env),
|
|
3886
|
+
headers: collect(body?.headers),
|
|
3887
|
+
...(typeof body?.enabled === 'boolean' ? { enabled: body.enabled } : {}),
|
|
3888
|
+
});
|
|
3889
|
+
if (!validated.ok) {
|
|
3890
|
+
writeJson(res, 400, { ok: false, error: validated.error });
|
|
3891
|
+
return;
|
|
3892
|
+
}
|
|
3893
|
+
const overwrite = body?.overwrite === true;
|
|
3894
|
+
const result = writeServerConfig(validated.config, {
|
|
3895
|
+
...(overwrite ? { force: true } : {}),
|
|
3896
|
+
// An overwrite from the page is an EDIT: it must not delete a credential
|
|
3897
|
+
// it was never allowed to display.
|
|
3898
|
+
...(overwrite ? { mergeEnv: true } : {}),
|
|
3899
|
+
warnings: validated.warnings,
|
|
3900
|
+
});
|
|
3901
|
+
writeJson(res, result.ok ? 200 : 400, {
|
|
3902
|
+
ok: result.ok,
|
|
3903
|
+
reason: result.reason,
|
|
3904
|
+
path: result.path,
|
|
3905
|
+
overwrote: result.overwrote,
|
|
3906
|
+
warnings: result.warnings,
|
|
3907
|
+
});
|
|
3908
|
+
})();
|
|
3909
|
+
return;
|
|
3910
|
+
}
|
|
3911
|
+
// POST /api/mcp/uninstall — remove a server's config file (catalog-installed or
|
|
3912
|
+
// hand-written; it is the same file either way).
|
|
3913
|
+
if (pathname === '/api/mcp/uninstall' && req.method === 'POST') {
|
|
3914
|
+
void (async () => {
|
|
3915
|
+
const session = adminSessions.validate(bearerToken(req));
|
|
3916
|
+
if (!session) {
|
|
3917
|
+
writeJson(res, 401, { ok: false, error: 'Not authenticated — log in first.' });
|
|
3918
|
+
return;
|
|
3919
|
+
}
|
|
3920
|
+
if (!roleCan(session.role, 'routing.operate')) {
|
|
3921
|
+
writeJson(res, 403, {
|
|
3922
|
+
ok: false,
|
|
3923
|
+
error: `Access denied — role '${session.role}' cannot remove MCP servers (requires admin or operator).`,
|
|
3924
|
+
});
|
|
3925
|
+
return;
|
|
3926
|
+
}
|
|
3927
|
+
const body = await readJsonBody(req);
|
|
3928
|
+
const name = typeof body?.name === 'string' ? body.name.trim() : '';
|
|
3929
|
+
const { uninstallCatalogServer } = await import('../mcp/catalog.js');
|
|
3930
|
+
const result = uninstallCatalogServer(name);
|
|
3931
|
+
writeJson(res, result.ok ? 200 : 404, { ok: result.ok, reason: result.reason });
|
|
3932
|
+
})();
|
|
3933
|
+
return;
|
|
3934
|
+
}
|
|
3617
3935
|
// ── Agent Hub skill toggles (P3) — admin-gated writes honored by the I7
|
|
3618
3936
|
// match gate (compiled findMatch + hub catalog), so the toggle is NEVER
|
|
3619
3937
|
// cosmetic. Same `skills.disabled[]` config the CLI writes; capability
|
|
@@ -7283,11 +7601,36 @@ function handleRequest(req, res) {
|
|
|
7283
7601
|
const requested = `${provider}${model ? `/${model}` : ''}`;
|
|
7284
7602
|
const served = result.provider ? `${result.provider}${result.model ? `/${result.model}` : ''}` : '';
|
|
7285
7603
|
const substituted = Boolean(served) && result.provider !== provider;
|
|
7604
|
+
/**
|
|
7605
|
+
* CAPABILITY CLASS — did the turn drop a class against the user's pin?
|
|
7606
|
+
*
|
|
7607
|
+
* Decided HERE from the pin the request carried and the model the engine
|
|
7608
|
+
* reported serving, because that is the one place both are known. The
|
|
7609
|
+
* rule is the user's own: a pinned model is a quality bar, so a handoff
|
|
7610
|
+
* that steps DOWN a class must be said out loud, not discovered later.
|
|
7611
|
+
*/
|
|
7612
|
+
const pinnedClass = model ? capabilityClassOf(model) : undefined;
|
|
7613
|
+
const servedClass = result.model ? capabilityClassOf(result.model) : undefined;
|
|
7614
|
+
const steppedDown = pinnedClass !== undefined &&
|
|
7615
|
+
servedClass !== undefined &&
|
|
7616
|
+
bandRank(servedClass) < bandRank(pinnedClass);
|
|
7286
7617
|
if (strict) {
|
|
7287
7618
|
if (result.generationFailed === true) {
|
|
7288
7619
|
routingNotice =
|
|
7289
7620
|
'Strict model mode is on, so the turn stopped rather than falling back to another model.';
|
|
7290
7621
|
}
|
|
7622
|
+
else if (substituted) {
|
|
7623
|
+
// Strict mode did NOT substitute on its own — the user chose a switch
|
|
7624
|
+
// from the pinned-failure question. Saying "the turn stopped" here
|
|
7625
|
+
// would contradict the answer they are reading.
|
|
7626
|
+
routingNotice =
|
|
7627
|
+
`Strict model mode is on: this turn ran on ${served} because you chose to switch after your pinned ${requested} did not answer.`;
|
|
7628
|
+
}
|
|
7629
|
+
}
|
|
7630
|
+
else if (steppedDown) {
|
|
7631
|
+
routingNotice =
|
|
7632
|
+
`We had to fall to a different model because no ${pinnedClass}-class model was available: ` +
|
|
7633
|
+
`your pinned ${requested} is ${pinnedClass} class, and this turn ran on ${served} (${servedClass} class).`;
|
|
7291
7634
|
}
|
|
7292
7635
|
else if (substituted) {
|
|
7293
7636
|
routingNotice = `Auto routing took over: this turn ran on ${served} because your pinned ${requested} was not available. To work with ${requested} only, enable strict model mode.`;
|
|
@@ -7307,7 +7650,11 @@ function handleRequest(req, res) {
|
|
|
7307
7650
|
// that reason with a "keep trying" offer for a request that cannot succeed,
|
|
7308
7651
|
// and would queue a background re-run of the very ask that refused.
|
|
7309
7652
|
if (result.generationFailed === true && result.refused !== true) {
|
|
7310
|
-
|
|
7653
|
+
// Does the engine's own content ALREADY explain this failure? Then the
|
|
7654
|
+
// broker adds only the OFFER — one failure, explained once (see
|
|
7655
|
+
// `renderModelBreadthReport`'s `offerOnly`).
|
|
7656
|
+
const alreadyExplained = /I couldn't finish|Tried \d+ model|was unable to do it|language model was unavailable/i.test(content);
|
|
7657
|
+
const report = chatRetryBroker.onFailure(sessionId, message, attemptMark, alreadyExplained ? { offerOnly: true } : undefined);
|
|
7311
7658
|
if (report) {
|
|
7312
7659
|
content = content.trim() ? `${content}\n\n${report}` : report;
|
|
7313
7660
|
retryQueued = true;
|