drafted 1.19.47 → 1.19.49
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 +32 -1
- package/package.json +1 -1
package/mcp/server.mjs
CHANGED
|
@@ -3308,6 +3308,7 @@ tool('fs', 'Navigate Drafted like a local filesystem. A FOLDER is the single con
|
|
|
3308
3308
|
recursive: z.boolean().optional().describe('[ls] recurse into subdirectories'),
|
|
3309
3309
|
lines: z.string().optional().describe('[read] line range (e.g. "1-50") — partial read; content is hashline-annotated so a later edit stays surgical'),
|
|
3310
3310
|
pattern: z.string().optional().describe('[ls] filter filenames (e.g. "*.html")'),
|
|
3311
|
+
readonly: z.boolean().optional().describe('[link] read-only frame link (symlink): mirror the SOURCE frame named by `to` (a frame UUID or /projects/<other-project>/<layer>/<lane>/<file>) into the CURRENT project, displayed read-only. The source project stays the single writer.'),
|
|
3311
3312
|
org: z.string().optional().describe('Org (id or name) for bare /wiki and /skills paths (org-scoped /o/<org>/... paths don\'t need it). Per-request only; project paths self-derive org from the project row.'),
|
|
3312
3313
|
projectId: PROJECT_OVERRIDE_PARAM,
|
|
3313
3314
|
}, async (args) => {
|
|
@@ -4018,7 +4019,12 @@ tool('fs', 'Navigate Drafted like a local filesystem. A FOLDER is the single con
|
|
|
4018
4019
|
// App frames (drafted:frame-type=app) carry a separate hydration state —
|
|
4019
4020
|
// return the state + a content preview rather than the full bundle, which
|
|
4020
4021
|
// is usually a large minified JS blob that would blow the tool-result cap.
|
|
4021
|
-
|
|
4022
|
+
// Classification comes from the server (result.appFrame — one detector,
|
|
4023
|
+
// from looksLikeAppFrame); the legacy regex below only covers servers that
|
|
4024
|
+
// predate the flag, and the server's answer always wins.
|
|
4025
|
+
const isAppFrame = result?.id && (result.appFrame === true ||
|
|
4026
|
+
(result.appFrame == null && /drafted:frame-type[^>]*content="app"/.test(result.content || '')));
|
|
4027
|
+
if (isAppFrame) {
|
|
4022
4028
|
let state = null;
|
|
4023
4029
|
try { const st = await api('GET', `/api/file/${result.id}/state`); state = st?.state ?? null; } catch { /* best-effort */ }
|
|
4024
4030
|
return ok({ appFrame: true, frameId: result.id, frameUrl: `${getServerUrl()}/f/${result.id}`, state, contentPreview: (result.content || '').slice(0, 500) });
|
|
@@ -4210,6 +4216,31 @@ tool('fs', 'Navigate Drafted like a local filesystem. A FOLDER is the single con
|
|
|
4210
4216
|
if (!filePath) return err(new Error(`${action} requires a source file path: /projects/<project>/<layer>/<lane>/<file>`));
|
|
4211
4217
|
const from = lane ? `/${layer}/${lane}/${filename}` : `/${layer}/${filename}`;
|
|
4212
4218
|
const body = { from };
|
|
4219
|
+
if (action === 'link' && args.readonly) {
|
|
4220
|
+
// Read-only frame link (symlink): mirror the frame INTO the current
|
|
4221
|
+
// project read-only. `to` names the SOURCE frame — a frame UUID or an
|
|
4222
|
+
// fs path in another project (/projects/<slug>/<layer>/<lane>/<file>).
|
|
4223
|
+
if (!to) return err(new Error('readonly link requires to=<source frame path in another project, or a frame UUID>'));
|
|
4224
|
+
const t = String(to);
|
|
4225
|
+
let sourceId;
|
|
4226
|
+
if (/^[0-9a-f-]{36}$/.test(t)) {
|
|
4227
|
+
sourceId = t;
|
|
4228
|
+
} else if (t.startsWith('/o/') && t.includes('/projects/')) {
|
|
4229
|
+
// Absolute path — the server mirror route parses it directly.
|
|
4230
|
+
sourceId = t;
|
|
4231
|
+
} else {
|
|
4232
|
+
let dest;
|
|
4233
|
+
try { dest = await resolveProjectsDestination(t); }
|
|
4234
|
+
catch (e) { return err(e); }
|
|
4235
|
+
if (!dest || !dest.meta || !dest.meta.id || dest.rest.length < 2) {
|
|
4236
|
+
return err(new Error('readonly link requires to=/projects/<project>/<layer>/<lane>/<file> or a frame UUID'));
|
|
4237
|
+
}
|
|
4238
|
+
const src = await api('GET', `/api/fs/${dest.rest.join('/')}?projectId=${dest.meta.id}`, undefined, orgHeader);
|
|
4239
|
+
if (!src?.id) return err(new Error(`Source frame not found: ${t}`));
|
|
4240
|
+
sourceId = src.id;
|
|
4241
|
+
}
|
|
4242
|
+
return ok(await api('POST', '/api/fs/link', { mirror: true, from: sourceId }, orgHeader));
|
|
4243
|
+
}
|
|
4213
4244
|
if (args.url) {
|
|
4214
4245
|
body.url = args.url;
|
|
4215
4246
|
} else if (to) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "drafted",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.49",
|
|
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": [
|