drafted 1.7.2 → 1.7.4
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/mcp/server.mjs +51 -4
- package/package.json +5 -2
package/mcp/server.mjs
CHANGED
|
@@ -350,7 +350,28 @@ async function api(method, path, body, _retried) {
|
|
|
350
350
|
data = { text };
|
|
351
351
|
}
|
|
352
352
|
|
|
353
|
-
if (!res.ok)
|
|
353
|
+
if (!res.ok) {
|
|
354
|
+
const msg = data.error || `HTTP ${res.status}`;
|
|
355
|
+
// The active project no longer resolves in the current org context.
|
|
356
|
+
// This is the silent-drift bug: project.open set a project, then
|
|
357
|
+
// something switched the active org (parallel agent, browser tab, or
|
|
358
|
+
// a get_org switch), and now the project is invisible. Clear our
|
|
359
|
+
// sticky reference so the next tool call doesn't append a stale
|
|
360
|
+
// projectId to its URL — and tell the agent what happened.
|
|
361
|
+
if ((res.status === 404 || /project not found/i.test(msg)) && pid && getState().projectId === pid) {
|
|
362
|
+
const meta = getState().projectMeta;
|
|
363
|
+
getState().projectId = null;
|
|
364
|
+
getState().projectMeta = null;
|
|
365
|
+
const sess = getSessionState();
|
|
366
|
+
sess.activeProjectId = null;
|
|
367
|
+
sess.activeProjectMeta = null;
|
|
368
|
+
throw new Error(
|
|
369
|
+
`${msg} — the active project (${meta?.slug || pid}) is no longer in the current org. ` +
|
|
370
|
+
`Active project cleared. Call project(action="open") to set a new one, or proceed without one for org-scoped tools (wiki, skill).`
|
|
371
|
+
);
|
|
372
|
+
}
|
|
373
|
+
throw new Error(msg);
|
|
374
|
+
}
|
|
354
375
|
return data;
|
|
355
376
|
}
|
|
356
377
|
|
|
@@ -436,6 +457,25 @@ function setMcpActiveProject(projectId, meta = null) {
|
|
|
436
457
|
sess.activeProjectMeta = meta;
|
|
437
458
|
}
|
|
438
459
|
|
|
460
|
+
// Clear the active project if its orgId no longer matches the current org.
|
|
461
|
+
// Catches the silent drift where org switches (via get_org switch, browser
|
|
462
|
+
// tab, parallel agent, etc.) leave the MCP session pointing at a project
|
|
463
|
+
// the API can no longer see — which surfaces as confusing "Project not
|
|
464
|
+
// found" errors on otherwise-valid tool calls.
|
|
465
|
+
async function ensureProjectMatchesOrg() {
|
|
466
|
+
const s = getState();
|
|
467
|
+
const meta = s.projectMeta;
|
|
468
|
+
if (!s.projectId || !meta?.orgId) return;
|
|
469
|
+
const currentOrgId = await getCurrentOrgId();
|
|
470
|
+
if (currentOrgId && currentOrgId !== meta.orgId) {
|
|
471
|
+
s.projectId = null;
|
|
472
|
+
s.projectMeta = null;
|
|
473
|
+
const sess = getSessionState();
|
|
474
|
+
sess.activeProjectId = null;
|
|
475
|
+
sess.activeProjectMeta = null;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
439
479
|
// Returns { id, slug, name, orgId } for the project this MCP session most
|
|
440
480
|
// recently opened — what frame mutations will actually target. Echoed on
|
|
441
481
|
// every mutation so silent cross-project drift is visible.
|
|
@@ -1808,9 +1848,16 @@ tool('skill', 'Manage the Drafted skill library. Skills are reusable prompts/gui
|
|
|
1808
1848
|
// empty-org / wiki-only sessions where there's no project to bind to.
|
|
1809
1849
|
const explicit = args.projectId;
|
|
1810
1850
|
const active = getState().projectId;
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1851
|
+
const pid = explicit || active;
|
|
1852
|
+
if (pid) {
|
|
1853
|
+
try {
|
|
1854
|
+
return ok(await api('GET', `/api/projects/${pid}/skills`));
|
|
1855
|
+
} catch (e) {
|
|
1856
|
+
// 404 / "not found" means the project isn't visible in the
|
|
1857
|
+
// current org (typical after an org switch). Fall through to
|
|
1858
|
+
// org-attached skills rather than bubbling a useless error.
|
|
1859
|
+
if (!/not found/i.test(e.message)) throw e;
|
|
1860
|
+
}
|
|
1814
1861
|
}
|
|
1815
1862
|
const orgId = await getCurrentOrgId();
|
|
1816
1863
|
if (!orgId) throw new Error('No active org. Call get_org first or pass projectId.');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "drafted",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.4",
|
|
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": [
|
|
@@ -25,7 +25,10 @@
|
|
|
25
25
|
"db:clean-sessions": "tsx src/auth/cleanup.ts",
|
|
26
26
|
"import:legacy": "tsx scripts/import-legacy.mts",
|
|
27
27
|
"test": "vitest run",
|
|
28
|
-
"test:watch": "vitest"
|
|
28
|
+
"test:watch": "vitest",
|
|
29
|
+
"version": "node scripts/sync-versions.mjs && git add plugin/.claude-plugin/plugin.json .claude-plugin/marketplace.json",
|
|
30
|
+
"version:check": "node scripts/sync-versions.mjs",
|
|
31
|
+
"postpublish": "bash scripts/sync-plugin.sh \"chore: sync plugin to v$npm_package_version\""
|
|
29
32
|
},
|
|
30
33
|
"dependencies": {
|
|
31
34
|
"@aws-sdk/client-s3": "^3.1007.0",
|