drafted 1.14.12 → 1.14.13

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.
Files changed (2) hide show
  1. package/mcp/server.mjs +17 -7
  2. package/package.json +1 -1
package/mcp/server.mjs CHANGED
@@ -1450,12 +1450,22 @@ async function requireBoundOrgForProjectlessMutation(explicitOrg) {
1450
1450
  return;
1451
1451
  }
1452
1452
  if (projectlessMutationNeedsOrg({ orgCount: orgs.length })) {
1453
+ // Actionable, not a dead end: name the orgs and the ONE call that binds this session,
1454
+ // so the agent recovers itself instead of stalling on the human. Project-less wiki and
1455
+ // skill work is a first-class flow — no project required, ever. The only thing refused
1456
+ // is GUESSING which org, which is what silently misfiled a page into the user's
1457
+ // default org. (Listing the orgs is safe: they're the caller's own memberships.)
1458
+ const names = orgs.map(o => o.name || o.id).filter(Boolean);
1453
1459
  throw new Error(
1454
- `Refusing to guess the org: no project is open and no explicit org was ` +
1455
- `given, but you belong to ${orgs.length} orgs a project-less wiki/skill write ` +
1456
- `would land in whichever org the session inherited. Pass org=... on this ` +
1457
- `call (org name or id), or open the relevant project first ` +
1458
- `(project(action="open") — the org derives from the project).`
1460
+ `Which org? A project-less wiki/skill write needs one, and you belong to ${orgs.length}: ` +
1461
+ `${names.join(', ')}. Don't guess an unaddressed write lands in whichever org this ` +
1462
+ `session inherited, which is how a page meant for one org ends up in another.\n` +
1463
+ `Recover in ONE call:\n` +
1464
+ ` • get_org(action="use", org="<name>") — binds this session's working org; every ` +
1465
+ `later project-less wiki/skill write then just works, no project needed.\n` +
1466
+ ` • or pass org="<name>" on this single call.\n` +
1467
+ ` • or project(action="open") if the work belongs to a project — the org derives from it.\n` +
1468
+ `Pick from the conversation if the org is clear from context; ask the user only if it isn't.`
1459
1469
  );
1460
1470
  }
1461
1471
  }
@@ -3548,7 +3558,7 @@ tool('skill', 'Manage the Drafted skill library. Skills are reusable prompts/gui
3548
3558
  path: z.string().optional().describe('[read_file|update_file] relative path inside skill directory (e.g. "examples/react.md")'),
3549
3559
  offset: z.number().optional().describe('[search|list|export] skip N results for pagination; [read_file] start reading at this byte offset (default 0) — for large files (e.g. a >90KB app-frame bundle) read in chunks using the returned nextOffset until truncated=false'),
3550
3560
  maxBytes: z.number().optional().describe('[read_file] return at most this many bytes from offset (default: whole remaining file). Response reports totalSize/offset/truncated/nextOffset.'),
3551
- org: z.string().optional().describe('[add] org (id or name) the skill is born in — defaults to the open project\'s org; [list|search|load] scope to this org; [fork|push|update|export|import] resolve/fork into this org. Per-request only — nothing is switched.'),
3561
+ org: z.string().optional().describe('[add] org (id or name) the skill is born in — defaults to the open project\'s org; [list|search|load] scope to this org; [fork|push|update|export|import] resolve/fork into this org. Per-request only — nothing is switched. NO PROJECT IS NEEDED: for project-less skill work either pass org= here, or bind the session once with get_org(action="use", org="<name>"). A multi-org caller that addresses neither is refused rather than guessed.'),
3552
3562
  setup: z.array(z.string()).optional().describe('[add|update] setup command(s) (in order) run on materialize to build a source-only skill, e.g. ["npm ci","npm run build"]'),
3553
3563
  files: z.array(z.object({ path: z.string(), content: z.string() })).optional().describe('[push] source files to push (path + UTF-8 content); server strips artifacts + enforces caps. [import] OKF bundle files inline — skills/<slug>/SKILL.md dirs and Skill/Playbook/SOP/Procedure-typed .md with name + description frontmatter become org skills. Caps: 500 files, 512KB/file, 5MB total.'),
3554
3564
  dir: z.string().optional().describe('[push|export|import] local directory. push: source tree to push instead of files[]; walked locally (heavy dirs, .skillinstall/, and .skillignore pre-filtered), server re-enforces; the dir\'s .gitignore is auto-updated to exclude .skillinstall/ (the rebuildable bundle). export: write the OKF bundle files here (default ./okf-skills-<org>). import: read the bundle from here (alternative to files[]).'),
@@ -3846,7 +3856,7 @@ tool('wiki', 'Per-org wiki. Markdown pages with paths as hierarchy. You and othe
3846
3856
  action: z.enum(['ls', 'recent', 'read', 'search', 'links', 'log', 'health', 'write', 'edit', 'mv', 'rm', 'cite', 'source-register', 'source-list', 'source-get', 'bulk-write', 'export', 'import']).describe('Operation to perform. export: the whole wiki as an OKF v0.1 bundle (local dir on stdio, download URL on remote, or format="files" for paged inline files). import: ingest an OKF bundle (files[] or local dir; dryRun supported).'),
3847
3857
  path: z.string().optional().describe('[ls|read|links|cite] wiki path. For ls: default / (root). For read: required. For links/cite: required unless pageId given. Reading `index.md` (any level) returns the SYNTHESIZED OKF directory listing.'),
3848
3858
  pageId: z.string().optional().describe('[read|edit|mv|rm|links] page UUID (from read/search). UUID-first: addresses the page directly, org auto-derives — no org needed and no path lookup. Preferred over path for an existing page.'),
3849
- org: z.string().optional().describe('Org slug or id to scope this call to (per-request only — nothing is switched). [write] the org the page is created in required when you belong to several orgs and no project is open. [search] restrict to this org (default: ALL your orgs). [ls|recent|read|links|log|health|edit|mv|rm|bulk-write] target this org\'s wiki instead of the open project\'s org. Ignored when a pageId is given (the page self-derives its org).'),
3859
+ org: z.string().optional().describe('Org slug or id to scope this call to (per-request only — nothing is switched). NO PROJECT IS NEEDED for wiki work: to write project-less, either pass org= here, or bind the session once with get_org(action="use", org="<name>") and then omit it. Multi-org callers MUST address the org one of those two ways — an unaddressed write is refused rather than guessed (it would land in whichever org the session inherited). [write] the org the page is created in. [search] restrict to this org (default: ALL your orgs). [ls|recent|read|links|log|health|edit|mv|rm|bulk-write] target this org\'s wiki instead of the open project\'s org. Ignored when a pageId is given (the page self-derives its org).'),
3850
3860
  recursive: z.boolean().optional().describe('[ls] list recursively with depth indicators'),
3851
3861
  limit: z.number().optional().describe('[recent|search|export] max results (recent default 10, search default 25, export files default 100)'),
3852
3862
  offset: z.number().optional().describe('[export] pagination offset for format="files"'),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "drafted",
3
- "version": "1.14.12",
3
+ "version": "1.14.13",
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": [