drafted 1.12.1 → 1.12.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
@@ -207,9 +207,50 @@ fi
207
207
 
208
208
  init_telemetry
209
209
 
210
- mkdir -p "$HOME/.drafted/npm-global"
211
- npm config set prefix "$HOME/.drafted/npm-global" >/dev/null
212
- export PATH="$HOME/.drafted/npm-global/bin:$PATH"
210
+ NPM_GLOBAL_PREFIX="$HOME/.drafted/npm-global"
211
+ mkdir -p "$NPM_GLOBAL_PREFIX"
212
+
213
+ # A `drafted` resolved elsewhere on PATH (a leftover install from before this
214
+ # fixed-prefix scheme, or a manual `npm i -g` under the default prefix) would
215
+ # permanently shadow the fixed-prefix copy: the updater keeps this prefix
216
+ # current, but the shell keeps running the stale one. Remove it at its source.
217
+ STALE_DRAFTED_BIN="$(command -v drafted 2>/dev/null || true)"
218
+ if [ -n "$STALE_DRAFTED_BIN" ]; then
219
+ # Derived from where the resolved binary actually sits (bin's grandparent),
220
+ # not `npm config get prefix` — that reflects our own target prefix once
221
+ # it's already been set on a prior run, which would make this a no-op on
222
+ # every machine that's already installed once (i.e. every real machine).
223
+ CANDIDATE_PREFIX="$(dirname "$(dirname "$STALE_DRAFTED_BIN")")"
224
+ if [ "$CANDIDATE_PREFIX" != "$NPM_GLOBAL_PREFIX" ] && [ -d "$CANDIDATE_PREFIX/lib/node_modules/drafted" ]; then
225
+ echo -e " ${YELLOW}Found a stale Drafted install at $CANDIDATE_PREFIX — removing it so it can't shadow the current one.${RESET}"
226
+ npm uninstall -g drafted --prefix "$CANDIDATE_PREFIX" >/dev/null 2>&1 || true
227
+ fi
228
+ fi
229
+
230
+ npm config set prefix "$NPM_GLOBAL_PREFIX" >/dev/null
231
+ export PATH="$NPM_GLOBAL_PREFIX/bin:$PATH"
232
+
233
+ # Persist the prefix's bin dir at the FRONT of PATH for future shells — without
234
+ # this, npm's prefix config makes `npm install -g` land in the right place, but
235
+ # a bare `drafted` in a new terminal keeps resolving through whatever was
236
+ # already on PATH (see the installedVersion() comment on the login-shell PATH
237
+ # gap below). Idempotent guarded block, same pattern as the agent-instructions
238
+ # markers further down.
239
+ persist_npm_global_path() {
240
+ local marker_begin="# BEGIN drafted-path"
241
+ local marker_end="# END drafted-path"
242
+ local line="export PATH=\"$NPM_GLOBAL_PREFIX/bin:\$PATH\""
243
+ local rc
244
+ case "$(basename "${SHELL:-}")" in
245
+ zsh) rc="$HOME/.zshrc" ;;
246
+ bash) rc="$HOME/.bash_profile" ;;
247
+ *) rc="$HOME/.profile" ;;
248
+ esac
249
+ [ -f "$rc" ] || : > "$rc"
250
+ grep -qF "$marker_begin" "$rc" 2>/dev/null && return 0
251
+ { echo ""; echo "$marker_begin"; echo "$line"; echo "$marker_end"; } >> "$rc"
252
+ }
253
+ persist_npm_global_path
213
254
 
214
255
  # ── Install ───────────────────────────────────────────────────────
215
256
 
package/mcp/server.mjs CHANGED
@@ -200,7 +200,7 @@ IMPORTANT: Any URL containing /f/{uuid} is a Drafted frame link — ALWAYS use r
200
200
  }, {
201
201
  // Initialize instructions: the agent-identity contract, so an agent learns its own
202
202
  // tab name + the right way to read it WITHOUT having to "think to" call a tool.
203
- instructions: `SESSION IDENTITY — read this first: you run as a NAMED session tab visible to the user on their Drafted surface. Your session has a human-readable name + emoji (e.g. "Sly Owl") — that name is how the user matches YOUR window to the tab they see, so identify yourself by it when it matters which agent you are. Read it from get_org (response field "session.name") or from the whoami tool; call whoami to refresh after a reconnect.`,
203
+ instructions: `SESSION IDENTITY — read this first: you run as a NAMED session tab visible to the user on their Drafted surface. Your session has a human-readable name (a Greek term, e.g. "Nous") — that name is how the user matches YOUR window to the tab they see, so identify yourself by it when it matters which agent you are. Read it from get_org (response field "session.name") or from the whoami tool; call whoami to refresh after a reconnect.`,
204
204
  });
205
205
 
206
206
  const layerKeys = Object.keys(LAYERS);
@@ -220,7 +220,7 @@ const TOOL_ANNOTATIONS = {
220
220
  auth: { title: 'Sign in', readOnlyHint: false, destructiveHint: false, openWorldHint: true, description: 'Sign in to Drafted. `action=get_link` returns a URL immediately and starts background approval polling; after the user opens the link, later Drafted tool calls also auto-consume the approved login. `action=login` opens a browser when needed and explicitly waits/polls for approval.' },
221
221
 
222
222
  // Identity — read-only introspection of THIS agent's session
223
- whoami: { title: 'Session identity', readOnlyHint: true, destructiveHint: false, openWorldHint: false, description: 'Return THIS agent session\'s identity: its server-assigned human-readable name + emoji (the correlation key between an agent window and its web-app session tab), sessionId, userId, orgId, active projectId, editor label, server URL, and surfaced/alive state. Read-only. Use this — not guesses from the host environment — to report which session you are.' },
223
+ whoami: { title: 'Session identity', readOnlyHint: true, destructiveHint: false, openWorldHint: false, description: 'Return THIS agent session\'s identity: its server-assigned human-readable name (the correlation key between an agent window and its web-app session tab), sessionId, userId, orgId, active projectId, editor label, server URL, and surfaced/alive state. Read-only. Use this — not guesses from the host environment — to report which session you are.' },
224
224
 
225
225
  // Projects
226
226
  project: { title: 'Projects', readOnlyHint: false, destructiveHint: false, openWorldHint: false, widgetUri: 'ui://widget/drafted-canvas-overview.html', description: 'Manage projects: list (start here), open (switch active project), create, update, move to another org.' },
@@ -1071,7 +1071,7 @@ function withProjectBreadcrumb(result) {
1071
1071
 
1072
1072
  let agentWs = null;
1073
1073
  let agentWsReconnectTimer = null;
1074
- // Cached agent-hello-ack: this agent's own surface identity (name/emoji/alive) as
1074
+ // Cached agent-hello-ack: this agent's own surface identity (name/capital/color/alive) as
1075
1075
  // assigned by the server. The playful name is the correlation key between an agent
1076
1076
  // window and its web-app session tab; whoami reads it from here.
1077
1077
  let agentSurface = null;
@@ -1134,7 +1134,7 @@ async function connectAgentWs() {
1134
1134
  if (m.type === 'agent-hello-ack') {
1135
1135
  agentSurface = {
1136
1136
  sessionId: m.sessionId, userId: m.userId, orgId: m.orgId, projectId: m.projectId,
1137
- name: m.name, emoji: m.emoji, alive: m.alive, surfaced: true,
1137
+ name: m.name, capital: m.capital, color: m.color, alive: m.alive, surfaced: true,
1138
1138
  capturedAt: Date.now(),
1139
1139
  };
1140
1140
  }
@@ -1517,7 +1517,7 @@ if (!isRemote) tool('auth', 'Sign in to Drafted. `action=get_link` returns a ver
1517
1517
  } catch (error) { return err(error); }
1518
1518
  });
1519
1519
 
1520
- // THIS-session surface identity: the playful name + emoji (correlation key between an
1520
+ // THIS-session surface identity: the session name + capital/color tile (correlation key between an
1521
1521
  // agent window and its web-app session tab), ids, and surfaced/alive state. Built from
1522
1522
  // the cached agent-hello-ack; falls back to /auth/me for userId/org before the first ack.
1523
1523
  // Shared by `whoami` AND surfaced in `get_org`'s response so an agent learns its name
@@ -1531,7 +1531,8 @@ async function sessionSurfaceBlock() {
1531
1531
  orgId: agentSurface.orgId ?? null,
1532
1532
  projectId: agentSurface.projectId ?? null,
1533
1533
  name: agentSurface.name,
1534
- emoji: agentSurface.emoji,
1534
+ capital: agentSurface.capital,
1535
+ color: agentSurface.color,
1535
1536
  surfaced: true,
1536
1537
  alive: !!agentSurface.alive,
1537
1538
  };
@@ -1551,14 +1552,15 @@ async function sessionSurfaceBlock() {
1551
1552
  orgId: me?.currentOrg?.id ?? null,
1552
1553
  projectId: getState().projectId ?? null,
1553
1554
  name: null,
1554
- emoji: null,
1555
+ capital: null,
1556
+ color: null,
1555
1557
  surfaced: false,
1556
1558
  alive: false,
1557
1559
  };
1558
1560
  }
1559
1561
 
1560
1562
  // Identity: report THIS agent session's own surface identity. Read-only — no state changed.
1561
- tool('whoami', 'Return THIS agent session\'s identity: its server-assigned human-readable name + emoji (the correlation key between an agent window and its web-app session tab), sessionId, userId, orgId, active projectId, editor label, server URL, and surfaced/alive state. Read-only.', {}, async () => {
1563
+ tool('whoami', 'Return THIS agent session\'s identity: its server-assigned human-readable name (the correlation key between an agent window and its web-app session tab), sessionId, userId, orgId, active projectId, editor label, server URL, and surfaced/alive state. Read-only.', {}, async () => {
1562
1564
  try {
1563
1565
  return ok({
1564
1566
  server: getServerUrl(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "drafted",
3
- "version": "1.12.1",
3
+ "version": "1.12.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": [