@sanctuary-framework/mcp-server 1.1.6 → 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 CHANGED
@@ -11909,7 +11909,7 @@ async function handleRequest(deps, req, res) {
11909
11909
  writeJSON(res, 200, { ok: true, mode: deps.sources.mode });
11910
11910
  return true;
11911
11911
  }
11912
- if (method === "GET" && (path === "/" || path === "/index.html")) {
11912
+ if (method === "GET" && (path === "/v1.0" || path === "/v1.0/" || path === "/v1.0/index.html")) {
11913
11913
  const snapshot = await getProtectionSnapshot(deps.sources);
11914
11914
  const html = renderDashboardHTML({ snapshot, authToken: deps.authToken });
11915
11915
  writeText(res, 200, html, "text/html; charset=utf-8");
@@ -12795,7 +12795,7 @@ function renderMain() {
12795
12795
  const main = document.getElementById("main");
12796
12796
  if (!main) return;
12797
12797
  switch (state.route) {
12798
- case "dashboard": main.innerHTML = renderChatThread(); break;
12798
+ case "dashboard": main.innerHTML = renderDashboardWelcome(); break;
12799
12799
  case "agents": main.innerHTML = renderAgentsList(); break;
12800
12800
  case "agent-detail": main.innerHTML = renderAgentDetail(); break;
12801
12801
  case "policy": main.innerHTML = renderPolicyCenter(); break;
@@ -12807,48 +12807,32 @@ function renderMain() {
12807
12807
  }
12808
12808
  }
12809
12809
 
12810
- // ── Render: chat thread ────────────────────────────────────────────────
12811
- function renderChatThread() {
12812
- const activeId = state.chatActiveAgentId;
12813
- const agent = activeId ? state.agents.find(function (a) { return a.agent_id === activeId; }) : null;
12814
- const header = '<header style="padding:8px 0;border-bottom:1px solid var(--rule);margin-bottom:8px;">' +
12815
- '<strong>' + escHtml(agent ? agent.agent_id : "Concierge") + '</strong>' +
12816
- ' <span class="muted">' + (agent ? "agent" : "Sanctuary advisory only. Operator-agent direct command via chat lands in v1.2.") + '</span>' +
12817
- '</header>';
12818
-
12819
- // Three message kinds. (1) operator (UI-side suggestions, not backend POST).
12820
- // (2) agent-initiated approvals from inbox filtered by agent_id. (3) activity
12821
- // events filtered by agent_id rendered as system-style.
12822
- const msgs = [];
12823
- if (!agent) {
12824
- msgs.push('<div class="chat-msg system"><strong>Concierge:</strong> Pick an agent in the right pane to scope the thread. Tier 1 actions appear here as approve/deny prompts. Free text is advisory only at v1.1.</div>');
12825
- } else {
12826
- const pending = state.inbox.filter(function (i) { return i.kind === "approval_pending" && i.agent_id === activeId && !i.resolved; });
12827
- pending.forEach(function (i) {
12828
- const text = renderTemplate(i.display_template_id, i.display_template_args);
12829
- msgs.push(
12830
- '<div class="chat-msg agent" data-msg-kind="agent-initiated" data-item-id="' + escHtml(i.item_id) + '">' +
12831
- '<div>' + escHtml(text) + '</div>' +
12832
- '<div style="margin-top:6px;display:flex;gap:6px;">' +
12833
- '<button class="btn btn-primary" data-action="inbox-approve" data-item-id="' + escHtml(i.item_id) + '">Approve</button>' +
12834
- '<button class="btn" data-action="inbox-deny" data-item-id="' + escHtml(i.item_id) + '">Deny</button>' +
12835
- '<button class="btn" data-action="show-details" data-item-id="' + escHtml(i.item_id) + '">Show details</button>' +
12836
- '</div>' +
12837
- '</div>'
12838
- );
12839
- });
12840
- const events = state.activity.filter(function (e) { return e.agent_id === activeId; }).slice(0, 20);
12841
- events.forEach(function (e) {
12842
- const text = renderTemplate(e.display_template_id, e.display_template_args);
12843
- msgs.push('<div class="chat-msg system"><span class="muted">' + escHtml(shortTime(e.emitted_at)) + '</span> ' + escHtml(text) + '</div>');
12844
- });
12845
- }
12846
-
12847
- const composer = '<form class="composer" id="chat-composer">' +
12848
- '<input type="text" placeholder="Suggestion to concierge. (Direct commands land in v1.2.)" id="chat-input" />' +
12849
- '<button type="submit" class="btn">Send</button>' +
12850
- '</form>';
12851
- return header + '<div class="chat-thread">' + (msgs.length ? msgs.join("\n") : '<p class="muted">No messages yet.</p>') + '</div>' + composer;
12810
+ // ── Render: dashboard welcome ──────────────────────────────────────────
12811
+ // v1.1.7: replaces the half-built chat surface that v1.1.6 shipped with
12812
+ // a "What you can do today" summary card mapping each nav target to
12813
+ // the operator action it enables. Direct concierge chat is a v1.2 work
12814
+ // package (WP-V1.2-3 + WP-V1.2-4).
12815
+ function renderDashboardWelcome() {
12816
+ return [
12817
+ '<h1>What you can do today</h1>',
12818
+ '<div class="card">',
12819
+ '<dl class="kv">',
12820
+ '<dt><a href="#agents">Agents</a></dt>',
12821
+ '<dd>Pause, resume, restart, lockdown, or unwrap any wrapped harness.</dd>',
12822
+ '<dt><a href="#policy">Policy</a></dt>',
12823
+ '<dd>Review the active policy bound to each agent.</dd>',
12824
+ '<dt><a href="#privacy">Privacy</a></dt>',
12825
+ '<dd>See what context is flowing to which provider per channel.</dd>',
12826
+ '<dt><a href="#coordination">Coordination</a></dt>',
12827
+ '<dd>Inspect intra-fortress agent coordination state.</dd>',
12828
+ '<dt><a href="#health">Health</a></dt>',
12829
+ '<dd>Check fortress posture, cocoon status, and dashboard refresh.</dd>',
12830
+ '<dt><a href="#exit-drill">Exit drill</a></dt>',
12831
+ '<dd>Snapshot, verify, and prepare a portable exit bundle.</dd>',
12832
+ '</dl>',
12833
+ '</div>',
12834
+ '<p class="muted">Direct chat with the concierge ships in v1.2.</p>'
12835
+ ].join("");
12852
12836
  }
12853
12837
 
12854
12838
  // ── Render: agents list / detail ───────────────────────────────────────
@@ -12887,8 +12871,10 @@ function renderAgentDetail() {
12887
12871
  '<dt>Status</dt><dd><span class="glyph ' + map.glyph + '"></span> ' + escHtml(map.label) + '</dd>' +
12888
12872
  '</dl>' +
12889
12873
  '</div>' +
12890
- '<div class="card"><h3>Timeline</h3>' + timeline + '</div>' +
12891
- '<button class="btn" data-action="set-route" data-route="dashboard">Open chat</button>';
12874
+ '<div class="card"><h3>Timeline</h3>' + timeline + '</div>';
12875
+ // v1.1.7: "Open chat" button removed alongside the half-built chat
12876
+ // surface (Finding EE). The agent-detail timeline + capability buttons
12877
+ // are the operator's interaction surface at v1.1; chat ships in v1.2.
12892
12878
  }
12893
12879
 
12894
12880
  // ── Render: privacy ────────────────────────────────────────────────────
@@ -13058,11 +13044,13 @@ function renderFortress() {
13058
13044
  : "This harness does not support " + mi.label.toLowerCase() + ".";
13059
13045
  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>';
13060
13046
  }).join("");
13061
- return '<div class="row" data-agent-row="' + escHtml(a.agent_id) + '">' +
13062
- '<span class="glyph ' + map.glyph + '" title="' + escHtml(REASON_LABELS[a.status_reason_class] || "") + '"></span>' +
13063
- '<div class="grow"><strong>' + escHtml(a.agent_id) + '</strong></div>' +
13064
- '<span class="pill">' + escHtml(map.label) + '</span>' +
13065
- '<div style="display:flex;gap:4px;flex-wrap:wrap;">' + buttons + '</div>' +
13047
+ return '<div class="row agent-row" data-agent-row="' + escHtml(a.agent_id) + '">' +
13048
+ '<div class="agent-row-head">' +
13049
+ '<span class="glyph ' + map.glyph + '" title="' + escHtml(REASON_LABELS[a.status_reason_class] || "") + '"></span>' +
13050
+ '<div class="grow"><strong>' + escHtml(a.agent_id) + '</strong></div>' +
13051
+ '<span class="pill">' + escHtml(map.label) + '</span>' +
13052
+ '</div>' +
13053
+ '<div class="agent-row-actions">' + buttons + '</div>' +
13066
13054
  '</div>';
13067
13055
  }).join("\n")
13068
13056
  : '<p class="muted">No agents wrapped.</p>';
@@ -13306,19 +13294,10 @@ document.addEventListener("click", function (ev) {
13306
13294
  }
13307
13295
  });
13308
13296
 
13309
- document.addEventListener("submit", function (ev) {
13310
- if (ev.target && ev.target.id === "chat-composer") {
13311
- ev.preventDefault();
13312
- const inp = document.getElementById("chat-input");
13313
- if (!inp) return;
13314
- const txt = inp.value.trim();
13315
- inp.value = "";
13316
- if (!txt) return;
13317
- // Concierge suggestion engine, NOT a backend command POST.
13318
- // Operator-typed direct commands land in v1.2.
13319
- toast("Concierge: I cannot run that as a command at v1.1. Use the inbox or the Agents view to take action.");
13320
- }
13321
- });
13297
+ // v1.1.7: chat composer submit handler removed alongside the half-built
13298
+ // chat surface (Finding EE). Direct concierge chat ships in v1.2; until
13299
+ // then the dashboard view renders a static welcome card with no form
13300
+ // inputs that could be confused for a working command surface.
13322
13301
 
13323
13302
  // Theme: system preference only at v1.1.
13324
13303
  const mq = window.matchMedia ? window.matchMedia("(prefers-color-scheme: dark)") : null;
@@ -13518,6 +13497,10 @@ body {
13518
13497
  .row { display: flex; align-items: center; gap: 8px; padding: 6px 0; border-bottom: 1px dashed var(--rule); }
13519
13498
  .row:last-child { border-bottom: 0; }
13520
13499
  .row .grow { flex: 1; min-width: 0; }
13500
+ .agent-row { flex-direction: column; align-items: stretch; gap: 6px; }
13501
+ .agent-row-head { display: flex; align-items: center; gap: 8px; min-width: 0; }
13502
+ .agent-row-head .grow { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
13503
+ .agent-row-actions { display: flex; flex-wrap: wrap; gap: 4px; }
13521
13504
  .kv { display: grid; grid-template-columns: max-content 1fr; gap: 4px 12px; font-size: 12px; }
13522
13505
  .kv dt { color: var(--ink-3); }
13523
13506
  .kv dd { margin: 0; color: var(--ink); }
@@ -13568,12 +13551,8 @@ body {
13568
13551
 
13569
13552
  // src/dashboard/v1_1/routes.ts
13570
13553
  function handleDashboardV11Route(deps, req, res) {
13571
- const routePath = deps.routePath ?? "/v1.1";
13572
- const host = req.headers.host || "localhost";
13573
- const url = new URL(req.url ?? "/", `http://${host}`);
13574
13554
  const method = (req.method ?? "GET").toUpperCase();
13575
13555
  if (method !== "GET") return false;
13576
- if (url.pathname !== routePath && url.pathname !== `${routePath}/`) return false;
13577
13556
  const html = renderDashboardV11Html(deps);
13578
13557
  res.writeHead(200, {
13579
13558
  "Content-Type": "text/html; charset=utf-8",
@@ -13621,7 +13600,7 @@ var init_v1_1 = __esm({
13621
13600
  // src/dashboard/v1_1/dispatch.ts
13622
13601
  async function dispatchV11Request(inputs, req, res, url, method) {
13623
13602
  const { bindings, authToken, loopbackAutoAuth } = inputs;
13624
- if (method === "GET" && (url.pathname === "/v1.1" || url.pathname === "/v1.1/")) {
13603
+ if (method === "GET" && (url.pathname === "/" || url.pathname === "/dashboard" || url.pathname === "/v1.1" || url.pathname === "/v1.1/")) {
13625
13604
  return handleDashboardV11Route(
13626
13605
  {
13627
13606
  identityId: bindings.identityId,
@@ -13666,7 +13645,7 @@ var init_dispatch = __esm({
13666
13645
  });
13667
13646
  function isDashboardViewRoute(method, path) {
13668
13647
  if (method !== "GET") return false;
13669
- return path === "/" || path === "/dashboard" || path === "/fortress" || path === "/events";
13648
+ return path === "/" || path === "/dashboard" || path === "/v1.0" || path === "/fortress" || path === "/events";
13670
13649
  }
13671
13650
  var SESSION_TTL_REMOTE_MS, SESSION_TTL_LOCAL_MS, MAX_SESSIONS, RATE_LIMIT_WINDOW_MS, RATE_LIMIT_GENERAL, RATE_LIMIT_DECISIONS, MAX_RATE_LIMIT_ENTRIES, DashboardApprovalChannel;
13672
13651
  var init_dashboard = __esm({
@@ -14186,7 +14165,7 @@ var init_dashboard = __esm({
14186
14165
  }
14187
14166
  return;
14188
14167
  }
14189
- if (method === "GET" && url.pathname === "/" && this.authToken) {
14168
+ if (method === "GET" && url.pathname === "/v1.0" && this.authToken) {
14190
14169
  if (!this.isAuthenticated(req, url)) {
14191
14170
  this.serveLoginPage(res);
14192
14171
  return;
@@ -14199,7 +14178,7 @@ var init_dashboard = __esm({
14199
14178
  try {
14200
14179
  if (method === "GET" && url.pathname === "/fortress") {
14201
14180
  this.serveFortressView(res);
14202
- } else if (method === "GET" && (url.pathname === "/" || url.pathname === "/dashboard")) {
14181
+ } else if (method === "GET" && url.pathname === "/v1.0") {
14203
14182
  if (this.fortressHTML) {
14204
14183
  this.serveFortressView(res);
14205
14184
  } else {