drafted 1.19.36 → 1.19.38
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 +29 -3
- package/package.json +1 -1
package/mcp/server.mjs
CHANGED
|
@@ -1596,7 +1596,12 @@ async function resolveProjectRef(ref) {
|
|
|
1596
1596
|
* One /api/projects fetch for the whole scan, not one per candidate.
|
|
1597
1597
|
*/
|
|
1598
1598
|
async function resolveFolderQualifiedProject(parts) {
|
|
1599
|
-
|
|
1599
|
+
// NOT `.catch(() => null)`. Swallowing the fetch turns "the session is gated"
|
|
1600
|
+
// or "the server is down" into "project not found", which is a wrong DIAGNOSIS,
|
|
1601
|
+
// not just a lost detail — it sends you hunting for a project instead of
|
|
1602
|
+
// reading the gate. Observed once for real: an unnamed session after an MCP
|
|
1603
|
+
// restart reported `project not found: Marketing/beoflow-marketing`.
|
|
1604
|
+
const data = await api('GET', '/api/projects');
|
|
1600
1605
|
const list = Array.isArray(data?.projects) ? data.projects : [];
|
|
1601
1606
|
const norm = (s) => String(s || '').toLowerCase();
|
|
1602
1607
|
for (let i = 1; i < parts.length; i++) {
|
|
@@ -3886,11 +3891,16 @@ tool('fs', 'Navigate Drafted like a local filesystem. A FOLDER is the single con
|
|
|
3886
3891
|
// before still resolves in one lookup and nothing pays for this.
|
|
3887
3892
|
projectRef = parts[0];
|
|
3888
3893
|
let tail = parts.slice(1);
|
|
3889
|
-
|
|
3894
|
+
// Keep WHY the first lookup failed. A bare `.catch(() => null)` here reports
|
|
3895
|
+
// every failure as "project not found", so a gated session or an unreachable
|
|
3896
|
+
// server reads as a missing project.
|
|
3897
|
+
let lookupError = null;
|
|
3898
|
+
let pathProject = await resolveProjectRef(projectRef).catch((e) => { lookupError = e; return null; });
|
|
3890
3899
|
if (!pathProject?.id && parts.length > 1) {
|
|
3891
3900
|
const found = await resolveFolderQualifiedProject(parts);
|
|
3892
3901
|
if (found) { projectRef = parts[found.index]; tail = parts.slice(found.index + 1); pathProject = found.meta; }
|
|
3893
3902
|
}
|
|
3903
|
+
if (!pathProject?.id && lookupError) return err(lookupError);
|
|
3894
3904
|
({ layer, lane, filename } = splitProjectTail(tail));
|
|
3895
3905
|
|
|
3896
3906
|
// fs grammar: the project comes from the PATH, not the shared session
|
|
@@ -4004,12 +4014,28 @@ tool('fs', 'Navigate Drafted like a local filesystem. A FOLDER is the single con
|
|
|
4004
4014
|
const body = {};
|
|
4005
4015
|
if (gw) {
|
|
4006
4016
|
// Google Workspace frames are created via the workspace endpoint (the
|
|
4007
|
-
// label drops the .google-* extension)
|
|
4017
|
+
// label drops the .google-* extension). Content (inline text, a local
|
|
4018
|
+
// text file, or base64) rides along: the server populates the Doc
|
|
4019
|
+
// (markdown → headings/bullets/styles/tables) or Sheet (CSV rows).
|
|
4020
|
+
let gwContent = null;
|
|
4021
|
+
if (content !== undefined && content !== null && content !== '') gwContent = String(content);
|
|
4022
|
+
else if (file_path) {
|
|
4023
|
+
const resolved = (() => { try { return resolve(file_path); } catch { return file_path; } })();
|
|
4024
|
+
if (!existsSync(resolved)) return err(new Error(`file not found: ${file_path}`));
|
|
4025
|
+
if (typeof file_path === 'string' && /\.(xlsx|xls|pdf|png|jpe?g|gif|webp|zip|docx)$/i.test(resolved)) {
|
|
4026
|
+
return err(new Error(`binary file ${basename(resolved)} cannot populate a ${gw}: pass content= (CSV for .google-sheet, markdown for .google-doc) or write a .xlsx frame instead`));
|
|
4027
|
+
}
|
|
4028
|
+
gwContent = readFileSync(resolved, 'utf8');
|
|
4029
|
+
} else if (base64) {
|
|
4030
|
+
try { gwContent = Buffer.from(base64, 'base64').toString('utf8'); } catch { gwContent = null; }
|
|
4031
|
+
}
|
|
4008
4032
|
const label = basename(filename, extname(filename)) || filename;
|
|
4009
4033
|
const result = await api('POST', '/api/google/workspace/create-frame', {
|
|
4010
4034
|
projectId: getState().projectId,
|
|
4011
4035
|
layer, lane, label, type: gw, title: title || label,
|
|
4036
|
+
...(gwContent ? { content: gwContent } : {}),
|
|
4012
4037
|
}, orgHeader);
|
|
4038
|
+
if (result?.contentError) return err(new Error(`${gw} created but content population failed: ${result.contentError} — populate via google doc-content/sheet-values actions`));
|
|
4013
4039
|
return ok({ ...result, path: `/${layer}/${lane}/${filename}`, sourceType: gw });
|
|
4014
4040
|
}
|
|
4015
4041
|
else if (content) body.content = content;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "drafted",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.38",
|
|
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": [
|