@sanctuary-framework/mcp-server 1.1.5 → 1.1.7
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/cli.cjs +62 -72
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +62 -72
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +62 -72
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +62 -72
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -4325,6 +4325,12 @@ interface HubPolicyAndBudgetSources {
|
|
|
4325
4325
|
* may persist records to disk or recompute them per call.
|
|
4326
4326
|
*/
|
|
4327
4327
|
interface HubAgentRegistrySource {
|
|
4328
|
+
/**
|
|
4329
|
+
* Insert or replace a record. Used by wrap-side registration and by
|
|
4330
|
+
* read-side persistence refresh to merge records written after dashboard
|
|
4331
|
+
* boot.
|
|
4332
|
+
*/
|
|
4333
|
+
put(record: LocalAgentRecord): void;
|
|
4328
4334
|
list(filter?: LocalAgentRegistryFilter): LocalAgentRecord[];
|
|
4329
4335
|
get(agentId: string): LocalAgentRecord | null;
|
|
4330
4336
|
/**
|
|
@@ -4350,6 +4356,12 @@ interface HubServiceDeps {
|
|
|
4350
4356
|
fortressId: string;
|
|
4351
4357
|
/** Local agent registry source. */
|
|
4352
4358
|
agentRegistry: HubAgentRegistrySource;
|
|
4359
|
+
/**
|
|
4360
|
+
* Optional best-effort persisted agent reader. When supplied, list
|
|
4361
|
+
* operations merge records written after hub construction before
|
|
4362
|
+
* returning the in-memory projection.
|
|
4363
|
+
*/
|
|
4364
|
+
readPersistedLocalAgents?: () => LocalAgentRecord[];
|
|
4353
4365
|
/** Inbox aggregation sources. */
|
|
4354
4366
|
inboxSources: HubInboxSources;
|
|
4355
4367
|
/** Activity feed sources. */
|
|
@@ -4403,6 +4415,7 @@ declare class HubService {
|
|
|
4403
4415
|
constructor(deps: HubServiceDeps);
|
|
4404
4416
|
private now;
|
|
4405
4417
|
private nowIso;
|
|
4418
|
+
private refreshPersistedLocalAgents;
|
|
4406
4419
|
listInbox(): HubInboxItem[];
|
|
4407
4420
|
resolveInboxItem(itemId: string, action: HubInboxAction): Promise<HubInboxItem>;
|
|
4408
4421
|
listAgents(filter?: LocalAgentRegistryFilter): LocalAgentRecord[];
|
package/dist/index.d.ts
CHANGED
|
@@ -4325,6 +4325,12 @@ interface HubPolicyAndBudgetSources {
|
|
|
4325
4325
|
* may persist records to disk or recompute them per call.
|
|
4326
4326
|
*/
|
|
4327
4327
|
interface HubAgentRegistrySource {
|
|
4328
|
+
/**
|
|
4329
|
+
* Insert or replace a record. Used by wrap-side registration and by
|
|
4330
|
+
* read-side persistence refresh to merge records written after dashboard
|
|
4331
|
+
* boot.
|
|
4332
|
+
*/
|
|
4333
|
+
put(record: LocalAgentRecord): void;
|
|
4328
4334
|
list(filter?: LocalAgentRegistryFilter): LocalAgentRecord[];
|
|
4329
4335
|
get(agentId: string): LocalAgentRecord | null;
|
|
4330
4336
|
/**
|
|
@@ -4350,6 +4356,12 @@ interface HubServiceDeps {
|
|
|
4350
4356
|
fortressId: string;
|
|
4351
4357
|
/** Local agent registry source. */
|
|
4352
4358
|
agentRegistry: HubAgentRegistrySource;
|
|
4359
|
+
/**
|
|
4360
|
+
* Optional best-effort persisted agent reader. When supplied, list
|
|
4361
|
+
* operations merge records written after hub construction before
|
|
4362
|
+
* returning the in-memory projection.
|
|
4363
|
+
*/
|
|
4364
|
+
readPersistedLocalAgents?: () => LocalAgentRecord[];
|
|
4353
4365
|
/** Inbox aggregation sources. */
|
|
4354
4366
|
inboxSources: HubInboxSources;
|
|
4355
4367
|
/** Activity feed sources. */
|
|
@@ -4403,6 +4415,7 @@ declare class HubService {
|
|
|
4403
4415
|
constructor(deps: HubServiceDeps);
|
|
4404
4416
|
private now;
|
|
4405
4417
|
private nowIso;
|
|
4418
|
+
private refreshPersistedLocalAgents;
|
|
4406
4419
|
listInbox(): HubInboxItem[];
|
|
4407
4420
|
resolveInboxItem(itemId: string, action: HubInboxAction): Promise<HubInboxItem>;
|
|
4408
4421
|
listAgents(filter?: LocalAgentRegistryFilter): LocalAgentRecord[];
|
package/dist/index.js
CHANGED
|
@@ -11160,7 +11160,7 @@ async function handleRequest(deps, req, res) {
|
|
|
11160
11160
|
writeJSON(res, 200, { ok: true, mode: deps.sources.mode });
|
|
11161
11161
|
return true;
|
|
11162
11162
|
}
|
|
11163
|
-
if (method === "GET" && (path === "/" || path === "/index.html")) {
|
|
11163
|
+
if (method === "GET" && (path === "/v1.0" || path === "/v1.0/" || path === "/v1.0/index.html")) {
|
|
11164
11164
|
const snapshot = await getProtectionSnapshot(deps.sources);
|
|
11165
11165
|
const html = renderDashboardHTML({ snapshot, authToken: deps.authToken });
|
|
11166
11166
|
writeText(res, 200, html, "text/html; charset=utf-8");
|
|
@@ -12001,7 +12001,7 @@ function renderMain() {
|
|
|
12001
12001
|
const main = document.getElementById("main");
|
|
12002
12002
|
if (!main) return;
|
|
12003
12003
|
switch (state.route) {
|
|
12004
|
-
case "dashboard": main.innerHTML =
|
|
12004
|
+
case "dashboard": main.innerHTML = renderDashboardWelcome(); break;
|
|
12005
12005
|
case "agents": main.innerHTML = renderAgentsList(); break;
|
|
12006
12006
|
case "agent-detail": main.innerHTML = renderAgentDetail(); break;
|
|
12007
12007
|
case "policy": main.innerHTML = renderPolicyCenter(); break;
|
|
@@ -12013,48 +12013,32 @@ function renderMain() {
|
|
|
12013
12013
|
}
|
|
12014
12014
|
}
|
|
12015
12015
|
|
|
12016
|
-
// ── Render:
|
|
12017
|
-
|
|
12018
|
-
|
|
12019
|
-
|
|
12020
|
-
|
|
12021
|
-
|
|
12022
|
-
|
|
12023
|
-
'</
|
|
12024
|
-
|
|
12025
|
-
|
|
12026
|
-
|
|
12027
|
-
|
|
12028
|
-
|
|
12029
|
-
|
|
12030
|
-
|
|
12031
|
-
|
|
12032
|
-
|
|
12033
|
-
|
|
12034
|
-
|
|
12035
|
-
|
|
12036
|
-
'<
|
|
12037
|
-
|
|
12038
|
-
|
|
12039
|
-
|
|
12040
|
-
|
|
12041
|
-
|
|
12042
|
-
'</div>' +
|
|
12043
|
-
'</div>'
|
|
12044
|
-
);
|
|
12045
|
-
});
|
|
12046
|
-
const events = state.activity.filter(function (e) { return e.agent_id === activeId; }).slice(0, 20);
|
|
12047
|
-
events.forEach(function (e) {
|
|
12048
|
-
const text = renderTemplate(e.display_template_id, e.display_template_args);
|
|
12049
|
-
msgs.push('<div class="chat-msg system"><span class="muted">' + escHtml(shortTime(e.emitted_at)) + '</span> ' + escHtml(text) + '</div>');
|
|
12050
|
-
});
|
|
12051
|
-
}
|
|
12052
|
-
|
|
12053
|
-
const composer = '<form class="composer" id="chat-composer">' +
|
|
12054
|
-
'<input type="text" placeholder="Suggestion to concierge. (Direct commands land in v1.2.)" id="chat-input" />' +
|
|
12055
|
-
'<button type="submit" class="btn">Send</button>' +
|
|
12056
|
-
'</form>';
|
|
12057
|
-
return header + '<div class="chat-thread">' + (msgs.length ? msgs.join("\n") : '<p class="muted">No messages yet.</p>') + '</div>' + composer;
|
|
12016
|
+
// ── Render: dashboard welcome ──────────────────────────────────────────
|
|
12017
|
+
// v1.1.7: replaces the half-built chat surface that v1.1.6 shipped with
|
|
12018
|
+
// a "What you can do today" summary card mapping each nav target to
|
|
12019
|
+
// the operator action it enables. Direct concierge chat is a v1.2 work
|
|
12020
|
+
// package (WP-V1.2-3 + WP-V1.2-4).
|
|
12021
|
+
function renderDashboardWelcome() {
|
|
12022
|
+
return [
|
|
12023
|
+
'<h1>What you can do today</h1>',
|
|
12024
|
+
'<div class="card">',
|
|
12025
|
+
'<dl class="kv">',
|
|
12026
|
+
'<dt><a href="#agents">Agents</a></dt>',
|
|
12027
|
+
'<dd>Pause, resume, restart, lockdown, or unwrap any wrapped harness.</dd>',
|
|
12028
|
+
'<dt><a href="#policy">Policy</a></dt>',
|
|
12029
|
+
'<dd>Review the active policy bound to each agent.</dd>',
|
|
12030
|
+
'<dt><a href="#privacy">Privacy</a></dt>',
|
|
12031
|
+
'<dd>See what context is flowing to which provider per channel.</dd>',
|
|
12032
|
+
'<dt><a href="#coordination">Coordination</a></dt>',
|
|
12033
|
+
'<dd>Inspect intra-fortress agent coordination state.</dd>',
|
|
12034
|
+
'<dt><a href="#health">Health</a></dt>',
|
|
12035
|
+
'<dd>Check fortress posture, cocoon status, and dashboard refresh.</dd>',
|
|
12036
|
+
'<dt><a href="#exit-drill">Exit drill</a></dt>',
|
|
12037
|
+
'<dd>Snapshot, verify, and prepare a portable exit bundle.</dd>',
|
|
12038
|
+
'</dl>',
|
|
12039
|
+
'</div>',
|
|
12040
|
+
'<p class="muted">Direct chat with the concierge ships in v1.2.</p>'
|
|
12041
|
+
].join("");
|
|
12058
12042
|
}
|
|
12059
12043
|
|
|
12060
12044
|
// ── Render: agents list / detail ───────────────────────────────────────
|
|
@@ -12093,8 +12077,10 @@ function renderAgentDetail() {
|
|
|
12093
12077
|
'<dt>Status</dt><dd><span class="glyph ' + map.glyph + '"></span> ' + escHtml(map.label) + '</dd>' +
|
|
12094
12078
|
'</dl>' +
|
|
12095
12079
|
'</div>' +
|
|
12096
|
-
'<div class="card"><h3>Timeline</h3>' + timeline + '</div>'
|
|
12097
|
-
|
|
12080
|
+
'<div class="card"><h3>Timeline</h3>' + timeline + '</div>';
|
|
12081
|
+
// v1.1.7: "Open chat" button removed alongside the half-built chat
|
|
12082
|
+
// surface (Finding EE). The agent-detail timeline + capability buttons
|
|
12083
|
+
// are the operator's interaction surface at v1.1; chat ships in v1.2.
|
|
12098
12084
|
}
|
|
12099
12085
|
|
|
12100
12086
|
// ── Render: privacy ────────────────────────────────────────────────────
|
|
@@ -12264,11 +12250,13 @@ function renderFortress() {
|
|
|
12264
12250
|
: "This harness does not support " + mi.label.toLowerCase() + ".";
|
|
12265
12251
|
return '<button class="btn" data-action="agent-' + mi.action + '" data-agent-id="' + escHtml(a.agent_id) + '"' + (mi.enabled ? '' : ' disabled') + ' title="' + escHtml(tip) + '">' + escHtml(mi.label) + '</button>';
|
|
12266
12252
|
}).join("");
|
|
12267
|
-
return '<div class="row" data-agent-row="' + escHtml(a.agent_id) + '">' +
|
|
12268
|
-
'<
|
|
12269
|
-
|
|
12270
|
-
|
|
12271
|
-
|
|
12253
|
+
return '<div class="row agent-row" data-agent-row="' + escHtml(a.agent_id) + '">' +
|
|
12254
|
+
'<div class="agent-row-head">' +
|
|
12255
|
+
'<span class="glyph ' + map.glyph + '" title="' + escHtml(REASON_LABELS[a.status_reason_class] || "") + '"></span>' +
|
|
12256
|
+
'<div class="grow"><strong>' + escHtml(a.agent_id) + '</strong></div>' +
|
|
12257
|
+
'<span class="pill">' + escHtml(map.label) + '</span>' +
|
|
12258
|
+
'</div>' +
|
|
12259
|
+
'<div class="agent-row-actions">' + buttons + '</div>' +
|
|
12272
12260
|
'</div>';
|
|
12273
12261
|
}).join("\n")
|
|
12274
12262
|
: '<p class="muted">No agents wrapped.</p>';
|
|
@@ -12512,19 +12500,10 @@ document.addEventListener("click", function (ev) {
|
|
|
12512
12500
|
}
|
|
12513
12501
|
});
|
|
12514
12502
|
|
|
12515
|
-
|
|
12516
|
-
|
|
12517
|
-
|
|
12518
|
-
|
|
12519
|
-
if (!inp) return;
|
|
12520
|
-
const txt = inp.value.trim();
|
|
12521
|
-
inp.value = "";
|
|
12522
|
-
if (!txt) return;
|
|
12523
|
-
// Concierge suggestion engine, NOT a backend command POST.
|
|
12524
|
-
// Operator-typed direct commands land in v1.2.
|
|
12525
|
-
toast("Concierge: I cannot run that as a command at v1.1. Use the inbox or the Agents view to take action.");
|
|
12526
|
-
}
|
|
12527
|
-
});
|
|
12503
|
+
// v1.1.7: chat composer submit handler removed alongside the half-built
|
|
12504
|
+
// chat surface (Finding EE). Direct concierge chat ships in v1.2; until
|
|
12505
|
+
// then the dashboard view renders a static welcome card with no form
|
|
12506
|
+
// inputs that could be confused for a working command surface.
|
|
12528
12507
|
|
|
12529
12508
|
// Theme: system preference only at v1.1.
|
|
12530
12509
|
const mq = window.matchMedia ? window.matchMedia("(prefers-color-scheme: dark)") : null;
|
|
@@ -12662,6 +12641,10 @@ body {
|
|
|
12662
12641
|
.row { display: flex; align-items: center; gap: 8px; padding: 6px 0; border-bottom: 1px dashed var(--rule); }
|
|
12663
12642
|
.row:last-child { border-bottom: 0; }
|
|
12664
12643
|
.row .grow { flex: 1; min-width: 0; }
|
|
12644
|
+
.agent-row { flex-direction: column; align-items: stretch; gap: 6px; }
|
|
12645
|
+
.agent-row-head { display: flex; align-items: center; gap: 8px; min-width: 0; }
|
|
12646
|
+
.agent-row-head .grow { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
12647
|
+
.agent-row-actions { display: flex; flex-wrap: wrap; gap: 4px; }
|
|
12665
12648
|
.kv { display: grid; grid-template-columns: max-content 1fr; gap: 4px 12px; font-size: 12px; }
|
|
12666
12649
|
.kv dt { color: var(--ink-3); }
|
|
12667
12650
|
.kv dd { margin: 0; color: var(--ink); }
|
|
@@ -12766,12 +12749,8 @@ function renderDashboardV11Html(options = {}) {
|
|
|
12766
12749
|
|
|
12767
12750
|
// src/dashboard/v1_1/routes.ts
|
|
12768
12751
|
function handleDashboardV11Route(deps, req, res) {
|
|
12769
|
-
const routePath = deps.routePath ?? "/v1.1";
|
|
12770
|
-
const host = req.headers.host || "localhost";
|
|
12771
|
-
const url = new URL(req.url ?? "/", `http://${host}`);
|
|
12772
12752
|
const method = (req.method ?? "GET").toUpperCase();
|
|
12773
12753
|
if (method !== "GET") return false;
|
|
12774
|
-
if (url.pathname !== routePath && url.pathname !== `${routePath}/`) return false;
|
|
12775
12754
|
const html = renderDashboardV11Html(deps);
|
|
12776
12755
|
res.writeHead(200, {
|
|
12777
12756
|
"Content-Type": "text/html; charset=utf-8",
|
|
@@ -12784,7 +12763,7 @@ function handleDashboardV11Route(deps, req, res) {
|
|
|
12784
12763
|
// src/dashboard/v1_1/dispatch.ts
|
|
12785
12764
|
async function dispatchV11Request(inputs, req, res, url, method) {
|
|
12786
12765
|
const { bindings, authToken, loopbackAutoAuth } = inputs;
|
|
12787
|
-
if (method === "GET" && (url.pathname === "/v1.1" || url.pathname === "/v1.1/")) {
|
|
12766
|
+
if (method === "GET" && (url.pathname === "/" || url.pathname === "/dashboard" || url.pathname === "/v1.1" || url.pathname === "/v1.1/")) {
|
|
12788
12767
|
return handleDashboardV11Route(
|
|
12789
12768
|
{
|
|
12790
12769
|
identityId: bindings.identityId,
|
|
@@ -12832,7 +12811,7 @@ var RATE_LIMIT_DECISIONS = 20;
|
|
|
12832
12811
|
var MAX_RATE_LIMIT_ENTRIES = 1e4;
|
|
12833
12812
|
function isDashboardViewRoute(method, path) {
|
|
12834
12813
|
if (method !== "GET") return false;
|
|
12835
|
-
return path === "/" || path === "/dashboard" || path === "/fortress" || path === "/events";
|
|
12814
|
+
return path === "/" || path === "/dashboard" || path === "/v1.0" || path === "/fortress" || path === "/events";
|
|
12836
12815
|
}
|
|
12837
12816
|
var DashboardApprovalChannel = class {
|
|
12838
12817
|
config;
|
|
@@ -13336,7 +13315,7 @@ var DashboardApprovalChannel = class {
|
|
|
13336
13315
|
}
|
|
13337
13316
|
return;
|
|
13338
13317
|
}
|
|
13339
|
-
if (method === "GET" && url.pathname === "/" && this.authToken) {
|
|
13318
|
+
if (method === "GET" && url.pathname === "/v1.0" && this.authToken) {
|
|
13340
13319
|
if (!this.isAuthenticated(req, url)) {
|
|
13341
13320
|
this.serveLoginPage(res);
|
|
13342
13321
|
return;
|
|
@@ -13349,7 +13328,7 @@ var DashboardApprovalChannel = class {
|
|
|
13349
13328
|
try {
|
|
13350
13329
|
if (method === "GET" && url.pathname === "/fortress") {
|
|
13351
13330
|
this.serveFortressView(res);
|
|
13352
|
-
} else if (method === "GET" &&
|
|
13331
|
+
} else if (method === "GET" && url.pathname === "/v1.0") {
|
|
13353
13332
|
if (this.fortressHTML) {
|
|
13354
13333
|
this.serveFortressView(res);
|
|
13355
13334
|
} else {
|
|
@@ -26871,6 +26850,13 @@ var HubService = class {
|
|
|
26871
26850
|
nowIso() {
|
|
26872
26851
|
return this.now().toISOString();
|
|
26873
26852
|
}
|
|
26853
|
+
refreshPersistedLocalAgents() {
|
|
26854
|
+
const readPersistedLocalAgents2 = this.deps.readPersistedLocalAgents;
|
|
26855
|
+
if (!readPersistedLocalAgents2) return;
|
|
26856
|
+
for (const record of readPersistedLocalAgents2()) {
|
|
26857
|
+
this.deps.agentRegistry.put(record);
|
|
26858
|
+
}
|
|
26859
|
+
}
|
|
26874
26860
|
// ── Inbox ───────────────────────────────────────────────────────────
|
|
26875
26861
|
listInbox() {
|
|
26876
26862
|
const items = aggregateInbox(this.deps.inboxSources, this.inboxStore);
|
|
@@ -26882,6 +26868,7 @@ var HubService = class {
|
|
|
26882
26868
|
}
|
|
26883
26869
|
// ── Agents ──────────────────────────────────────────────────────────
|
|
26884
26870
|
listAgents(filter) {
|
|
26871
|
+
this.refreshPersistedLocalAgents();
|
|
26885
26872
|
const safeFilter = {
|
|
26886
26873
|
...filter ?? {},
|
|
26887
26874
|
identity_id: this.deps.identityId
|
|
@@ -27346,10 +27333,13 @@ var CapabilityErrorAgentController = class {
|
|
|
27346
27333
|
function buildV11Bindings(inputs) {
|
|
27347
27334
|
const seed = inputs.storagePath !== void 0 ? readPersistedLocalAgents(inputs.storagePath) : [];
|
|
27348
27335
|
const registry = new InMemoryLocalAgentRegistry(seed);
|
|
27336
|
+
const storagePath = inputs.storagePath;
|
|
27337
|
+
const readPersisted = storagePath !== void 0 ? () => readPersistedLocalAgents(storagePath) : void 0;
|
|
27349
27338
|
const hubService = new HubService({
|
|
27350
27339
|
identityId: inputs.identityId,
|
|
27351
27340
|
fortressId: inputs.fortressId,
|
|
27352
27341
|
agentRegistry: registry,
|
|
27342
|
+
...readPersisted ? { readPersistedLocalAgents: readPersisted } : {},
|
|
27353
27343
|
inboxSources: {
|
|
27354
27344
|
listPendingApprovals: () => [],
|
|
27355
27345
|
listRecentBlockedEgress: () => [],
|