drafted 1.21.1 → 1.21.3

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/install-mcp.sh CHANGED
@@ -333,6 +333,14 @@ fi
333
333
  if [ "$INSTALL_MODE" = "local" ] && [ -f "$SCRIPT_DIR/mcp/server.mjs" ]; then
334
334
  DRAFTED_MCP_COMMAND="$(command -v node)"
335
335
  DRAFTED_MCP_ARGS_JSON="$(node -e 'console.log(JSON.stringify([process.argv[1]]))' "$SCRIPT_DIR/mcp/server.mjs")"
336
+ elif [ -n "${NPM_ROOT:-}" ] && [ -f "$MCP_SERVER_MODULE" ]; then
337
+ # Absolute node + server file, NOT the drafted-mcp shebang (#!/usr/bin/env node):
338
+ # GUI clients build their own PATH, and Claude Desktop put an old nvm Node (v16,
339
+ # no fetch) first, so every tool call failed as "unreachable" (2026-10-06). This
340
+ # is the node checked >= 22 above; the auto-updater re-runs this script, so the
341
+ # registration follows it if it moves.
342
+ DRAFTED_MCP_COMMAND="$(command -v node)"
343
+ DRAFTED_MCP_ARGS_JSON="$(node -e 'console.log(JSON.stringify([process.argv[1]]))' "$MCP_SERVER_MODULE")"
336
344
  else
337
345
  DRAFTED_MCP_COMMAND="$(command -v drafted-mcp)"
338
346
  DRAFTED_MCP_ARGS_JSON="[]"
package/mcp/server.mjs CHANGED
@@ -27,6 +27,14 @@ import { createGateState, markSearched, g1Block, g2Block, g3Block, selectWithinB
27
27
  import { loadPersistedProject, savePersistedProject } from './active-project-store.mjs';
28
28
  import { probeRepo, resolveAddress, addressNote } from './repo-address.mjs';
29
29
 
30
+ // Node 18+ only (global fetch). A GUI client that resolves an old Node (Claude
31
+ // Desktop put nvm v16 first on its PATH, 2026-10-06) otherwise fails every tool call
32
+ // as "unreachable" instead of saying why.
33
+ if (typeof fetch !== 'function') {
34
+ console.error(`Drafted MCP needs Node.js 18 or newer, but is running on ${process.version}. Re-run the Drafted installer, or point your MCP client at a newer node.`);
35
+ process.exit(1);
36
+ }
37
+
30
38
  // Frame actions that mutate content — gated by G1 (wiki search before editing).
31
39
  // Read-style actions (read, search, versions, get_*/read_*) are exempt.
32
40
  const G1_MUTATING_FRAME_ACTIONS = new Set([
@@ -1053,7 +1061,14 @@ async function cloneSession() {
1053
1061
  // id (stable per machine) so they ALSO keep one stable session/name across restarts
1054
1062
  // instead of churning a fresh session every process. (Org is per-request, so a
1055
1063
  // shared child session does NOT cause cross-agent org clobbering.)
1056
- const agentKey = (process.env.DRAFTED_AGENT_NAME || '').trim() || bootstrapId;
1064
+ //
1065
+ // A Causeway-launched agent keys on its Causeway session: without that, a single-org
1066
+ // user's concurrent anonymous agents dedupe to ONE shared session and one surface, so
1067
+ // a dashboard following one of them shows all of them (embed-follow contract §1.3).
1068
+ const causewaySession = (process.env.CAUSEWAY_SESSION_ID || '').trim();
1069
+ const agentKey = (process.env.DRAFTED_AGENT_NAME || '').trim()
1070
+ || (causewaySession ? `causeway-session:${causewaySession}` : '')
1071
+ || bootstrapId;
1057
1072
  const res = await serverFetch(`${getServerUrl()}/auth/session/clone`, {
1058
1073
  method: 'POST',
1059
1074
  headers: { 'Content-Type': 'application/json', Cookie: `gc_session=${bootstrapId}` },
@@ -1802,7 +1817,10 @@ async function connectAgentWs() {
1802
1817
  // moment it connects — before opening any project. Project work later flips it active.
1803
1818
  // suggestedName (basename of the working directory) lets the server offer it in the
1804
1819
  // name-before-work gate message and as the tab placeholder.
1805
- try { agentWs.send(JSON.stringify({ type: 'agent-hello', agentLabel: getAgentLabel(), suggestedName: getSuggestedSessionName() })); } catch {}
1820
+ // externalSessionId: the Causeway session this agent runs in, opaque to Drafted, so the
1821
+ // Causeway dashboard can follow this session (GET /api/surfaces?external=).
1822
+ const externalSessionId = (process.env.CAUSEWAY_SESSION_ID || '').trim() || undefined;
1823
+ try { agentWs.send(JSON.stringify({ type: 'agent-hello', agentLabel: getAgentLabel(), suggestedName: getSuggestedSessionName(), externalSessionId })); } catch {}
1806
1824
  // Local capabilities for the Get set up page: only a status word, never the
1807
1825
  // Google account, scopes or client. Same open-race guard as the hello.
1808
1826
  if (!isRemote) detectGwsStatus().then((gws) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "drafted",
3
- "version": "1.21.1",
3
+ "version": "1.21.3",
4
4
  "description": "Drafted — visual thinking surface for humans and AI agents. Renders HTML, markdown, images, and code as frames on a zoomable canvas, with MCP tools for AI agents and real-time sync for humans.",
5
5
  "type": "module",
6
6
  "files": [