drafted 1.14.7 → 1.14.9
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/cli/drafted.mjs +10 -4
- package/mcp/server.mjs +4 -60
- package/package.json +1 -1
package/cli/drafted.mjs
CHANGED
|
@@ -1591,9 +1591,12 @@ async function syncOneSkill(ref, outDir, org) {
|
|
|
1591
1591
|
mkdirSync(dirname(full), { recursive: true });
|
|
1592
1592
|
writeFileSync(full, content);
|
|
1593
1593
|
}
|
|
1594
|
-
// createdBy
|
|
1595
|
-
//
|
|
1596
|
-
|
|
1594
|
+
// createdBy + forkedFrom decide whether this skill's setup may auto-run: shell authored by
|
|
1595
|
+
// someone else must not run unattended on sync. forkedFrom is load-bearing — the CLI/MCP
|
|
1596
|
+
// AUTO-forks a global/other-org skill on use, which copies the source author's setup but
|
|
1597
|
+
// stamps createdBy = the forking (victim) user, so createdBy alone would mislabel foreign
|
|
1598
|
+
// setup as self-authored. A forked skill is never treated as self-authored.
|
|
1599
|
+
return { ref, slug, hash, status: 'ok', createdBy: skill.createdBy ?? null, forkedFrom: skill.forkedFrom ?? null };
|
|
1597
1600
|
}
|
|
1598
1601
|
|
|
1599
1602
|
const skillCmd = program.command('skill').description('Skill library operations');
|
|
@@ -1626,7 +1629,10 @@ skillCmd
|
|
|
1626
1629
|
// authored by another org member, a fork, or an imported bundle must NOT run their
|
|
1627
1630
|
// shell unattended (Causeway auto-syncs pinned skills), or a teammate's skill is
|
|
1628
1631
|
// RCE on this host. `--allow-untrusted-setup` is the explicit opt-in.
|
|
1629
|
-
|
|
1632
|
+
// Self-authored = created by me AND not a fork (a fork carries another author's
|
|
1633
|
+
// setup under my createdBy — see syncOneSkill). Forks/other-authored require the
|
|
1634
|
+
// explicit opt-in.
|
|
1635
|
+
const selfAuthored = r.createdBy && auth?.userId && r.createdBy === auth.userId && !r.forkedFrom;
|
|
1630
1636
|
if (selfAuthored || opts.allowUntrustedSetup) {
|
|
1631
1637
|
const s = runSkillSetup(join(opts.out, r.slug));
|
|
1632
1638
|
r.setup = s.skipped ? 'none' : (s.ok ? 'ok' : 'failed');
|
package/mcp/server.mjs
CHANGED
|
@@ -267,9 +267,7 @@ const TOOL_ANNOTATIONS = {
|
|
|
267
267
|
// Assets
|
|
268
268
|
asset: { title: 'Assets', readOnlyHint: false, destructiveHint: false, openWorldHint: false, description: 'Manage project assets (CSS/JS/images/fonts referenced by frames). `action=upload` or `action=list`.' },
|
|
269
269
|
|
|
270
|
-
//
|
|
271
|
-
shape: { title: 'Add shape', readOnlyHint: false, destructiveHint: false, openWorldHint: false },
|
|
272
|
-
group: { title: 'Create group', readOnlyHint: false, destructiveHint: false, openWorldHint: false },
|
|
270
|
+
// Connectors / layout
|
|
273
271
|
connector: { title: 'Connectors', readOnlyHint: false, destructiveHint: true, openWorldHint: false, description: 'Connect or disconnect frames with arrows on the surface. `action=connect` or `action=disconnect`.' },
|
|
274
272
|
layout: { title: 'Auto-layout', readOnlyHint: false, destructiveHint: false, openWorldHint: false },
|
|
275
273
|
|
|
@@ -307,8 +305,6 @@ function isMutatingToolCall(name, args = {}) {
|
|
|
307
305
|
case 'minion':
|
|
308
306
|
return ['create', 'update', 'enable', 'disable', 'delete', 'test_start', 'test_say', 'test_resolve'].includes(action);
|
|
309
307
|
case 'rm':
|
|
310
|
-
case 'shape':
|
|
311
|
-
case 'group':
|
|
312
308
|
case 'connector':
|
|
313
309
|
case 'layout':
|
|
314
310
|
return true;
|
|
@@ -1824,7 +1820,7 @@ tool('health', {}, async () => {
|
|
|
1824
1820
|
|
|
1825
1821
|
// ── Project management tools (direct HTTP) ────────────────────────
|
|
1826
1822
|
|
|
1827
|
-
tool('project', 'START HERE for project management. Dispatch by `action`: list (lists all projects across all orgs — always call first), open (bind this agent session to a project; required before reading/writing frames — the org derives from the project), create (new project; org= names where it is born), update (change name/folder/description/layers), move (transfer to another org), export (the project as an OKF v0.1 bundle — <layer>/<lane>/<file>.md concepts, index.md/log.md synthesized), import (ingest an OKF bundle: concepts become markdown document frames, links between them become connectors; dryRun supported). There is no org switching: for project-less work (wiki/skills) pass org=... on the call. **Skill gate:** projects with attached skills will REJECT all mutations (write, edit, mv, rm,
|
|
1823
|
+
tool('project', 'START HERE for project management. Dispatch by `action`: list (lists all projects across all orgs — always call first), open (bind this agent session to a project; required before reading/writing frames — the org derives from the project), create (new project; org= names where it is born), update (change name/folder/description/layers), move (transfer to another org), export (the project as an OKF v0.1 bundle — <layer>/<lane>/<file>.md concepts, index.md/log.md synthesized), import (ingest an OKF bundle: concepts become markdown document frames, links between them become connectors; dryRun supported). There is no org switching: for project-less work (wiki/skills) pass org=... on the call. **Skill gate:** projects with attached skills will REJECT all mutations (write, edit, mv, rm, connector, layout, layer, asset upload) until you have loaded each attached skill via skill(action="load"). Skills tell you HOW to do the work — they\'re not optional. Open returns the attached skill list and auto-inlines content for projects with ≤3 skills.', {
|
|
1828
1824
|
action: z.enum(['list', 'open', 'create', 'update', 'move', 'export', 'import']).describe('Operation to perform.'),
|
|
1829
1825
|
projectId: z.string().optional().describe('[open|update|move|export|import] project ID. Get IDs from action=list. For export/import: defaults to the bound project.'),
|
|
1830
1826
|
name: z.string().optional().describe('[create|update] project name'),
|
|
@@ -2157,7 +2153,7 @@ tool('focus', {
|
|
|
2157
2153
|
} catch (error) { return err(error); }
|
|
2158
2154
|
});
|
|
2159
2155
|
|
|
2160
|
-
tool('screenshot', 'Render a PNG via headless browser. `scope=frame` captures a single frame (default 1440×900, fullPage). `scope=canvas` captures a region of the project surface (default 1600×1200, typically the "plans" layer where
|
|
2156
|
+
tool('screenshot', 'Render a PNG via headless browser. `scope=frame` captures a single frame (default 1440×900, fullPage). `scope=canvas` captures a region of the project surface (default 1600×1200, typically the "plans" layer where frames live).', {
|
|
2161
2157
|
scope: z.enum(['frame', 'canvas']).describe('What to capture.'),
|
|
2162
2158
|
target: z.string().optional().describe('[scope=frame] frame URL, UUID, or /{layer}/{lane}/{filename} path.'),
|
|
2163
2159
|
slug: z.string().optional().describe('[scope=canvas] project slug. Defaults to the currently active project.'),
|
|
@@ -3293,56 +3289,6 @@ tool('asset', 'Manage supporting files (CSS, JS, images, fonts) in the ACTIVE PR
|
|
|
3293
3289
|
} catch (error) { return err(error); }
|
|
3294
3290
|
});
|
|
3295
3291
|
|
|
3296
|
-
// ── Shape tool ───────────────────────────────────────────────────────
|
|
3297
|
-
|
|
3298
|
-
tool('shape', 'Create a flowchart shape on the surface. Shapes are lightweight text nodes — use them for flowcharts, process diagrams, and decision trees. Connect shapes with connector(action="connect"), then call layout to auto-arrange.', {
|
|
3299
|
-
text: z.string().describe('Text to display inside the shape. Supports multi-line with \\n.'),
|
|
3300
|
-
shape: z.enum(['rectangle', 'diamond', 'oval', 'pill']).optional().default('rectangle').describe('Shape type: rectangle (process/action), diamond (decision), oval (start/end), pill (rounded step)'),
|
|
3301
|
-
layer: z.string().optional().describe('Layer to place the shape in (default: plans)'),
|
|
3302
|
-
lane: z.string().optional().describe('Lane within the layer (default: default)'),
|
|
3303
|
-
color: z.string().optional().describe('Border color (CSS color string)'),
|
|
3304
|
-
fill: z.string().optional().describe('Background fill color (CSS color string)'),
|
|
3305
|
-
textColor: z.string().optional().describe('Text color (CSS color string)'),
|
|
3306
|
-
group: z.string().optional().describe('Group ID to assign this shape to (for swim lane clustering). Use the ID returned by the group tool.'),
|
|
3307
|
-
width: z.number().optional().describe('Explicit width in pixels (overrides auto-sizing from text)'),
|
|
3308
|
-
height: z.number().optional().describe('Explicit height in pixels (overrides auto-sizing from text)'),
|
|
3309
|
-
layoutIgnore: z.boolean().optional().describe('Exclude this shape from auto-layout. Use for annotations, labels, or manually positioned elements.'),
|
|
3310
|
-
}, async ({ text, shape, layer, lane, color, fill, textColor, group, width, height, layoutIgnore }) => {
|
|
3311
|
-
try {
|
|
3312
|
-
const body = { text, shape };
|
|
3313
|
-
if (layer) body.layer = layer;
|
|
3314
|
-
if (lane) body.lane = lane;
|
|
3315
|
-
if (color) body.color = color;
|
|
3316
|
-
if (fill) body.fill = fill;
|
|
3317
|
-
if (textColor) body.textColor = textColor;
|
|
3318
|
-
if (group) body.group = group;
|
|
3319
|
-
if (width) body.width = width;
|
|
3320
|
-
if (height) body.height = height;
|
|
3321
|
-
if (layoutIgnore) body.layoutIgnore = true;
|
|
3322
|
-
const result = await api('POST', '/api/fs/shape', body);
|
|
3323
|
-
return ok(result);
|
|
3324
|
-
} catch (error) { return err(error); }
|
|
3325
|
-
});
|
|
3326
|
-
|
|
3327
|
-
tool('group', 'Create a group (swim lane / region) on the surface. Groups are labeled, colored background areas that visually contain shapes. Assign shapes to a group using the group parameter on the shape tool. Use layout with groups=true to auto-cluster.', {
|
|
3328
|
-
label: z.string().describe('Group label text (displayed in the header bar)'),
|
|
3329
|
-
color: z.string().optional().describe('Header bar and border color (CSS color string)'),
|
|
3330
|
-
fill: z.string().optional().describe('Background fill color (CSS color string). Defaults to a tinted version of color.'),
|
|
3331
|
-
layer: z.string().optional().describe('Layer to place the group in (default: plans)'),
|
|
3332
|
-
lane: z.string().optional().describe('Lane within the layer (default: default)'),
|
|
3333
|
-
order: z.number().optional().describe('Sort order for group positioning (lower = first). Default: 0'),
|
|
3334
|
-
}, async ({ label, color, fill, layer, lane, order }) => {
|
|
3335
|
-
try {
|
|
3336
|
-
const body = { label };
|
|
3337
|
-
if (color) body.color = color;
|
|
3338
|
-
if (fill) body.fill = fill;
|
|
3339
|
-
if (layer) body.layer = layer;
|
|
3340
|
-
if (lane) body.lane = lane;
|
|
3341
|
-
if (order != null) body.order = order;
|
|
3342
|
-
const result = await api('POST', '/api/fs/group', body);
|
|
3343
|
-
return ok(result);
|
|
3344
|
-
} catch (error) { return err(error); }
|
|
3345
|
-
});
|
|
3346
3292
|
// ── Connector tools ───────────────────────────────────────────────
|
|
3347
3293
|
|
|
3348
3294
|
tool('connector', 'Create or remove connectors (arrows) between frames on the surface. `action=connect` adds an arrow from source to target. `action=disconnect` removes one — pass either connectorId directly or source+target to find and delete.', {
|
|
@@ -3393,11 +3339,9 @@ tool('connector', 'Create or remove connectors (arrows) between frames on the su
|
|
|
3393
3339
|
|
|
3394
3340
|
tool('layout', 'Auto-arrange frames using graph layout algorithm. Positions connected frames as a directed graph.', {
|
|
3395
3341
|
direction: z.enum(['TB', 'LR', 'BT', 'RL']).optional().default('TB').describe('Layout direction: TB (top-bottom), LR (left-right), BT (bottom-top), RL (right-left)'),
|
|
3396
|
-
|
|
3397
|
-
}, async ({ direction, groups }) => {
|
|
3342
|
+
}, async ({ direction }) => {
|
|
3398
3343
|
try {
|
|
3399
3344
|
const body = { direction };
|
|
3400
|
-
if (groups) body.groups = true;
|
|
3401
3345
|
const result = await api('POST', '/api/layout', body);
|
|
3402
3346
|
return ok(result);
|
|
3403
3347
|
} catch (error) { return err(error); }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "drafted",
|
|
3
|
-
"version": "1.14.
|
|
3
|
+
"version": "1.14.9",
|
|
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": [
|