drafted 1.19.52 → 1.19.53

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 +16 -14
  2. package/package.json +14 -4
package/mcp/server.mjs CHANGED
@@ -174,7 +174,7 @@ export function textFromLocalFile(filePath) {
174
174
  // validation, and every handler stay byte-for-byte unchanged.
175
175
  const REMOTE_JSON_STRING_PARAMS = {
176
176
  fs: ['ops', 'state'],
177
- minion: ['target', 'checklist', 'output'],
177
+ minion: ['target', 'checklist', 'output', 'context'],
178
178
  trigger: ['payload'],
179
179
  };
180
180
 
@@ -466,7 +466,7 @@ const TOOL_ANNOTATIONS = {
466
466
  screenshot: { title: 'Screenshot', readOnlyHint: true, destructiveHint: false, openWorldHint: false, description: 'Render a PNG via headless browser. `scope=frame` for a single frame, `scope=canvas` for a region of the project surface.' },
467
467
 
468
468
  // Minions — checklist-driven intake surfaces bound to a project
469
- minion: { title: 'Minions', readOnlyHint: false, destructiveHint: true, openWorldHint: false, description: 'Manage Minions: checklist-driven intake surfaces that guide a consumer through a checklist (via a shareable /c/<slug>-<token> link) and write a producible into the project. Dispatch by `action`: meta, list, get, create, update, enable, disable, delete. QA your own Minions with test_start/test_say/test_resolve — drive the checklist conversation yourself (works even when disabled). Requires the agent allowlist.' },
469
+ minion: { title: 'Minions', readOnlyHint: false, destructiveHint: true, openWorldHint: false, description: 'Manage Minions: Drafted\'s agent for people OUTSIDE the org (bidders, clients, suppliers). A visitor opens a shareable /c/<slug>-<token> link, the Minion guides them through a checklist, writes ONE submission record into the project, and on submit marks it needs_review and queues it on output.handoff (a queue trigger) for YOUR agent to claim with trigger pending/claim/complete. A Minion never sends, shares or contacts anyone — outbound follow-up is your job. Everything in a Minion\'s config and its context pack is visible to anyone holding the link. Dispatch by `action`: meta, list, get, create, update, enable, disable, delete. QA your own Minions with test_start/test_say (works even when disabled). Requires the agent allowlist.' },
470
470
  trigger: { title: 'Inbound triggers', readOnlyHint: false, destructiveHint: true, openWorldHint: true, description: 'Manage inbound webhook triggers for the ACTIVE PROJECT: an external system (AppSheet bot, GitHub, form tool) POSTs to the trigger URL and the server runs an agent conversation in the project from the stored prompt template + payload. Dispatch by `action`: create (returns URL + secret token ONCE — relay it to the user immediately, not retrievable later), list, update (enable/disable, edit template, daily limit, executor), rotate (new token), test (fire a synthetic delivery), deliveries (audit log), delete; for executor="queue" triggers, pending/claim/complete let a LOCAL agent poll and work queued deliveries. Requires the agent allowlist.' },
471
471
  fs: { title: 'Filesystem', readOnlyHint: false, destructiveHint: true, openWorldHint: false, description: 'Navigate Drafted like a local filesystem: /wiki/<path> pages, /skills/<slug> procedures, /projects/<folder?>/<project>/<layer>/<lane>/<file> frames. Verbs: ls, read, write, edit, mv, rm, search, link, unlink, links.' },
472
472
  // Google Drive mirror triage. Mutating (resolve/retry_all/sync rewrite frame
@@ -479,7 +479,7 @@ function isMutatingToolCall(name, args = {}) {
479
479
  const action = args?.action;
480
480
  switch (name) {
481
481
  case 'minion':
482
- return ['create', 'update', 'enable', 'disable', 'delete', 'test_start', 'test_say', 'test_resolve'].includes(action);
482
+ return ['create', 'update', 'enable', 'disable', 'delete', 'test_start', 'test_say'].includes(action);
483
483
  case 'trigger':
484
484
  return ['create', 'update', 'rotate', 'delete'].includes(action);
485
485
  case 'fs':
@@ -3152,12 +3152,10 @@ function ensureSkillInstallIgnored(dir) {
3152
3152
 
3153
3153
 
3154
3154
  tool('minion', {
3155
- action: z.enum(['meta', 'list', 'get', 'create', 'update', 'enable', 'disable', 'delete', 'test_start', 'test_say', 'test_resolve']).describe('Operation to perform. test_* drive a QA conversation against a Minion you own (even disabled) to verify it end-to-end.'),
3155
+ action: z.enum(['meta', 'list', 'get', 'create', 'update', 'enable', 'disable', 'delete', 'test_start', 'test_say']).describe('Operation to perform. test_* drive a QA conversation against a Minion you own (even disabled) to verify it end-to-end.'),
3156
3156
  id: z.string().optional().describe('[get|update|enable|disable|delete|test_*] Minion ID (UUID)'),
3157
3157
  text: z.string().optional().describe('[test_say] the consumer message to send to your test run'),
3158
3158
  fresh: z.boolean().optional().describe('[test_start] start a brand-new run instead of resuming your latest'),
3159
- actionId: z.string().optional().describe('[test_resolve] id of the pending action to resolve'),
3160
- approve: z.boolean().optional().describe('[test_resolve] approve (default true) or reject the pending action'),
3161
3159
  projectId: z.string().optional().describe('[meta|list|create] the project this Minion belongs to — REQUIRED, as a path (/projects/<name> or /projects/<folder>/<name>), slug, or UUID. Minions are project-scoped: they write producibles into that project\'s surface. No session fallback — name the project.'),
3162
3160
  name: z.string().optional().describe('[create|update] Minion name'),
3163
3161
  description: z.string().optional().describe('[create|update] one-line description shown to the consumer'),
@@ -3186,8 +3184,15 @@ tool('minion', {
3186
3184
  sheet: z.string().describe('existing Google Sheet frame path or id to append rows to'),
3187
3185
  tab: z.string().optional().describe('sheet tab/range name to append to, e.g. "Erfassung" (defaults to Sheet1)'),
3188
3186
  columns: z.array(z.string()).optional().describe('columns in order; a link to the produced record is included'),
3189
- }).optional().describe('also append one row per submission to an existing sheet, linking the produced record'),
3187
+ }).optional().describe('one row per submission in an existing sheet. With a handoff the row travels in the handoff payload for your agent to append; without one the Minion appends it (raw values, no read access)'),
3188
+ handoff: z.object({
3189
+ triggerId: z.string().describe('a trigger with executor "queue" in the SAME project'),
3190
+ }).optional().describe('where a submitted record is queued for your connected agent to claim (trigger pending/claim/complete); the payload is marked trust:"untrusted-external"'),
3190
3191
  }).optional().describe('[create|update] where/how the producible lands'),
3192
+ context: z.object({
3193
+ frames: z.array(z.string()).describe('frame ids in the SAME project, max 20'),
3194
+ }).optional().describe('[create|update] the brief pack the Minion may read and answer from (read_brief). DISCLOSED to every visitor — include only what they may see. The Minion cannot read anything else in the org.'),
3195
+ visitorDailyLimit: z.number().optional().describe('[create|update] turns per visitor per UTC day (default 30); dailyLimit is shared by all visitors'),
3191
3196
  limit: z.number().optional().describe('[list] max results per page (default 25, max 100)'),
3192
3197
  offset: z.number().optional().describe('[list] skip N results for pagination (default 0)'),
3193
3198
  compact: z.boolean().optional().describe('[list] return only {id,slug,name,enabled,projectId} per Minion'),
@@ -3216,20 +3221,22 @@ tool('minion', {
3216
3221
  }
3217
3222
  case 'create': {
3218
3223
  // projectId lives in the BODY (the POST route reads body, ignores the query).
3219
- const { name, description, target, checklist, output, enabled } = args;
3224
+ const { name, description, target, checklist, output, enabled, context, visitorDailyLimit } = args;
3220
3225
  if (!name || !target || !Array.isArray(checklist) || !output) {
3221
3226
  throw new Error('name, target, checklist[], and output are required for action=create');
3222
3227
  }
3223
3228
  const body = { projectId: project.id, name, target, checklist, output };
3224
3229
  if (description !== undefined) body.description = description;
3225
3230
  if (enabled !== undefined) body.enabled = enabled;
3231
+ if (context !== undefined) body.context = context;
3232
+ if (visitorDailyLimit !== undefined) body.visitorDailyLimit = visitorDailyLimit;
3226
3233
  const created = await scoped(() => api('POST', '/api/minions', body));
3227
3234
  return ok({ ...created, projectPath });
3228
3235
  }
3229
3236
  case 'update': {
3230
3237
  if (!args.id) throw new Error('id is required for action=update');
3231
3238
  const body = {};
3232
- for (const k of ['name', 'description', 'target', 'checklist', 'output', 'enabled']) {
3239
+ for (const k of ['name', 'description', 'target', 'checklist', 'output', 'enabled', 'context', 'visitorDailyLimit']) {
3233
3240
  if (args[k] !== undefined) body[k] = args[k];
3234
3241
  }
3235
3242
  if (Object.keys(body).length === 0) throw new Error('At least one field is required for action=update');
@@ -3253,11 +3260,6 @@ tool('minion', {
3253
3260
  if (!args.text) throw new Error('text is required for action=test_say');
3254
3261
  return ok(await api('POST', `/api/minions/${args.id}/test-message`, { content: args.text }));
3255
3262
  }
3256
- case 'test_resolve': {
3257
- if (!args.id) throw new Error('id is required for action=test_resolve');
3258
- if (!args.actionId) throw new Error('actionId is required for action=test_resolve');
3259
- return ok(await api('POST', `/api/minions/${args.id}/test-resolve`, { actionId: args.actionId, approve: args.approve !== false }));
3260
- }
3261
3263
  default:
3262
3264
  throw new Error(`Unknown minion action: ${action}`);
3263
3265
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "drafted",
3
- "version": "1.19.52",
3
+ "version": "1.19.53",
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": [
@@ -63,19 +63,29 @@
63
63
  "lucide": "^1.16.0",
64
64
  "mdast-util-from-markdown": "^2.0.3",
65
65
  "multer": "^2.1.1",
66
- "nodemailer": "^8.0.2",
66
+ "nodemailer": "^10.0.13",
67
67
  "parse5": "^8.0.1",
68
68
  "pg": "^8.20.0",
69
69
  "playwright": "^1.58.2",
70
- "puppeteer": "^24.37.5",
70
+ "puppeteer": "^25.12.0",
71
71
  "qrcode-terminal": "^0.12.0",
72
72
  "react": "^18.3.1",
73
73
  "react-dom": "^18.3.1",
74
- "sharp": "^0.34.5",
74
+ "sharp": "^0.35.5",
75
75
  "ws": "^8.21.3",
76
76
  "yaml": "^2.8.3",
77
77
  "zod": "^4.3.6"
78
78
  },
79
+ "overrides": {
80
+ "@excalidraw/excalidraw": {
81
+ "nanoid": "^3.3.19"
82
+ },
83
+ "@excalidraw/mermaid-to-excalidraw": {
84
+ "nanoid": "^5.1.16"
85
+ },
86
+ "immutable": "^4.3.9",
87
+ "lodash-es": "^4.18.1"
88
+ },
79
89
  "keywords": [
80
90
  "design",
81
91
  "canvas",