drafted 1.11.32 → 1.11.33
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 +37 -0
- package/install-mcp.sh +2 -4
- package/mcp/server.mjs +30 -4
- package/package.json +1 -1
package/cli/drafted.mjs
CHANGED
|
@@ -2014,6 +2014,43 @@ collectorCmd
|
|
|
2014
2014
|
.option('--format <fmt>', 'output format: json or text', 'text')
|
|
2015
2015
|
.action((id, opts) => collectorSetEnabled(id, false, opts.format));
|
|
2016
2016
|
|
|
2017
|
+
async function collectorTestPost(id, path, body, format) {
|
|
2018
|
+
requireLogin();
|
|
2019
|
+
const server = getServerUrl().replace(/\/$/, '');
|
|
2020
|
+
const res = await authFetch(`${server}/api/collectors/${encodeURIComponent(id)}/${path}`, {
|
|
2021
|
+
method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body || {}),
|
|
2022
|
+
});
|
|
2023
|
+
const data = await res.json().catch(() => ({}));
|
|
2024
|
+
if (!res.ok) {
|
|
2025
|
+
if (format === 'json') console.log(JSON.stringify({ status: res.status === 404 ? 'not-found' : 'error', error: data.error || `HTTP ${res.status}` }));
|
|
2026
|
+
else console.log(['error', data.error || `HTTP ${res.status}`].join('\t'));
|
|
2027
|
+
process.exit(1);
|
|
2028
|
+
}
|
|
2029
|
+
console.log(JSON.stringify(data));
|
|
2030
|
+
}
|
|
2031
|
+
|
|
2032
|
+
collectorCmd
|
|
2033
|
+
.command('test-start <id>')
|
|
2034
|
+
.description('QA: start (or resume) a test run of a collector you own — works even when disabled. --fresh for a new run.')
|
|
2035
|
+
.option('--fresh', 'start a brand-new run instead of resuming', false)
|
|
2036
|
+
.option('--format <fmt>', 'output format: json (default)', 'json')
|
|
2037
|
+
.action((id, opts) => collectorTestPost(id, 'test-start', { fresh: !!opts.fresh }, opts.format));
|
|
2038
|
+
|
|
2039
|
+
collectorCmd
|
|
2040
|
+
.command('test-say <id>')
|
|
2041
|
+
.description('QA: send a text answer to your test run; returns the agent reply, checklist state, pending actions.')
|
|
2042
|
+
.requiredOption('--text <text>', 'the consumer message to send')
|
|
2043
|
+
.option('--format <fmt>', 'output format: json (default)', 'json')
|
|
2044
|
+
.action((id, opts) => collectorTestPost(id, 'test-message', { content: opts.text }, opts.format));
|
|
2045
|
+
|
|
2046
|
+
collectorCmd
|
|
2047
|
+
.command('test-resolve <id>')
|
|
2048
|
+
.description('QA: approve or reject a pending destructive action in your test run.')
|
|
2049
|
+
.requiredOption('--action <actionId>', 'the pending action id')
|
|
2050
|
+
.option('--reject', 'reject instead of approve', false)
|
|
2051
|
+
.option('--format <fmt>', 'output format: json (default)', 'json')
|
|
2052
|
+
.action((id, opts) => collectorTestPost(id, 'test-resolve', { actionId: opts.action, approve: !opts.reject }, opts.format));
|
|
2053
|
+
|
|
2017
2054
|
collectorCmd
|
|
2018
2055
|
.command('delete <id>')
|
|
2019
2056
|
.description('Delete a collector (past submissions are kept as history)')
|
package/install-mcp.sh
CHANGED
|
@@ -664,14 +664,12 @@ install_desktop_app() {
|
|
|
664
664
|
<string>live.drafted.desktop</string>
|
|
665
665
|
<key>ProgramArguments</key>
|
|
666
666
|
<array>
|
|
667
|
-
<string
|
|
668
|
-
<string>-a</string>
|
|
669
|
-
<string>$app_bundle</string>
|
|
667
|
+
<string>$app_exe</string>
|
|
670
668
|
</array>
|
|
671
669
|
<key>RunAtLoad</key>
|
|
672
670
|
<true/>
|
|
673
671
|
<key>KeepAlive</key>
|
|
674
|
-
<
|
|
672
|
+
<true/>
|
|
675
673
|
</dict>
|
|
676
674
|
</plist>
|
|
677
675
|
PLIST
|
package/mcp/server.mjs
CHANGED
|
@@ -249,7 +249,7 @@ const TOOL_ANNOTATIONS = {
|
|
|
249
249
|
wiki: { title: 'Wiki', readOnlyHint: false, destructiveHint: true, openWorldHint: false, description: 'Per-org wiki. Markdown pages with paths as hierarchy. Dispatch by `action`.' },
|
|
250
250
|
|
|
251
251
|
// Collectors — checklist-driven, Minion-run intake surfaces bound to a project
|
|
252
|
-
collector: { title: 'Collectors', readOnlyHint: false, destructiveHint: true, openWorldHint: false, description: 'Manage Collectors: checklist-driven intake surfaces that guide a consumer through a checklist (via a shareable /c/<slug> link) and then write a producible into the project. Dispatch by `action`: meta (discover layers/lanes/frames), list, get, create, update, enable, disable, delete. Requires the agent allowlist (same gate as Minion).' },
|
|
252
|
+
collector: { title: 'Collectors', readOnlyHint: false, destructiveHint: true, openWorldHint: false, description: 'Manage Collectors: checklist-driven intake surfaces that guide a consumer through a checklist (via a shareable /c/<slug> link) and then write a producible into the project. Dispatch by `action`: meta (discover layers/lanes/frames), list, get, create, update, enable, disable, delete. QA your own collectors with test_start/test_say/test_resolve — drive the checklist conversation yourself (works even when disabled) and verify it produces the right Doc/Sheet output. Requires the agent allowlist (same gate as Minion).' },
|
|
253
253
|
};
|
|
254
254
|
|
|
255
255
|
function isMutatingToolCall(name, args = {}) {
|
|
@@ -276,7 +276,7 @@ function isMutatingToolCall(name, args = {}) {
|
|
|
276
276
|
case 'wiki':
|
|
277
277
|
return ['log', 'write', 'edit', 'mv', 'rm', 'source-register', 'bulk-write'].includes(action);
|
|
278
278
|
case 'collector':
|
|
279
|
-
return ['create', 'update', 'enable', 'disable', 'delete'].includes(action);
|
|
279
|
+
return ['create', 'update', 'enable', 'disable', 'delete', 'test_start', 'test_say', 'test_resolve'].includes(action);
|
|
280
280
|
case 'rm':
|
|
281
281
|
case 'shape':
|
|
282
282
|
case 'group':
|
|
@@ -1045,6 +1045,9 @@ async function connectAgentWs() {
|
|
|
1045
1045
|
|
|
1046
1046
|
agentWs.on('open', () => {
|
|
1047
1047
|
console.error('[MCP-WS] Connected');
|
|
1048
|
+
// Announce presence immediately so the agent surfaces (greyed/idle, no project) the
|
|
1049
|
+
// moment it connects — before opening any project. Project work later flips it active.
|
|
1050
|
+
try { agentWs.send(JSON.stringify({ type: 'agent-hello', agentLabel: getAgentLabel() })); } catch {}
|
|
1048
1051
|
if (getState().projectId) {
|
|
1049
1052
|
agentWs.send(JSON.stringify({ type: 'join', projectId: getState().projectId, agent: true, agentLabel: getAgentLabel() }));
|
|
1050
1053
|
}
|
|
@@ -3663,8 +3666,12 @@ function collectorGateError(e) {
|
|
|
3663
3666
|
}
|
|
3664
3667
|
|
|
3665
3668
|
tool('collector', {
|
|
3666
|
-
action: z.enum(['meta', 'list', 'get', 'create', 'update', 'enable', 'disable', 'delete']).describe('Operation to perform.'),
|
|
3667
|
-
id: z.string().optional().describe('[get|update|enable|disable|delete] collector ID (UUID)'),
|
|
3669
|
+
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 collector you own (even disabled) to verify it end-to-end.'),
|
|
3670
|
+
id: z.string().optional().describe('[get|update|enable|disable|delete|test_*] collector ID (UUID)'),
|
|
3671
|
+
text: z.string().optional().describe('[test_say] the consumer message to send to your test run'),
|
|
3672
|
+
fresh: z.boolean().optional().describe('[test_start] start a brand-new run instead of resuming your latest'),
|
|
3673
|
+
actionId: z.string().optional().describe('[test_resolve] id of the pending action to resolve'),
|
|
3674
|
+
approve: z.boolean().optional().describe('[test_resolve] approve (default true) or reject the pending action'),
|
|
3668
3675
|
projectId: z.string().optional().describe('[create|meta] project to bind/scope to (defaults to the active project). Operates on the session’s active org — open the target project first via project(action="open"), or get_org(action="switch") to change org.'),
|
|
3669
3676
|
name: z.string().optional().describe('[create|update] collector name'),
|
|
3670
3677
|
description: z.string().optional().describe('[create|update] one-line description shown to the consumer'),
|
|
@@ -3688,6 +3695,11 @@ tool('collector', {
|
|
|
3688
3695
|
filenameTemplate: z.string().optional().describe('e.g. "<id>.md"'),
|
|
3689
3696
|
skillSlug: z.string().optional().describe('skill that shapes the produced frame'),
|
|
3690
3697
|
grouping: z.string().optional().describe('"lane" gives each submission its own lane'),
|
|
3698
|
+
format: z.enum(['markdown', 'google-doc', 'google-sheet', 'google-slide']).optional().describe('primary producible format; google-* require the org Drive connected (default markdown)'),
|
|
3699
|
+
register: z.object({
|
|
3700
|
+
sheet: z.string().describe('existing Google Sheet frame path or id to append rows to'),
|
|
3701
|
+
columns: z.array(z.string()).optional().describe('columns in order; a link to the produced record is included'),
|
|
3702
|
+
}).optional().describe('also append one row per submission to an existing sheet, linking the produced record'),
|
|
3691
3703
|
}).optional().describe('[create|update] where/how the producible lands'),
|
|
3692
3704
|
limit: z.number().optional().describe('[list] max results per page (default 25, max 100)'),
|
|
3693
3705
|
offset: z.number().optional().describe('[list] skip N results for pagination (default 0)'),
|
|
@@ -3745,6 +3757,20 @@ tool('collector', {
|
|
|
3745
3757
|
if (!args.id) throw new Error('id is required for action=delete');
|
|
3746
3758
|
return ok(await api('DELETE', `/api/collectors/${args.id}`));
|
|
3747
3759
|
}
|
|
3760
|
+
case 'test_start': {
|
|
3761
|
+
if (!args.id) throw new Error('id is required for action=test_start');
|
|
3762
|
+
return ok(await api('POST', `/api/collectors/${args.id}/test-start`, { fresh: !!args.fresh }));
|
|
3763
|
+
}
|
|
3764
|
+
case 'test_say': {
|
|
3765
|
+
if (!args.id) throw new Error('id is required for action=test_say');
|
|
3766
|
+
if (!args.text) throw new Error('text is required for action=test_say');
|
|
3767
|
+
return ok(await api('POST', `/api/collectors/${args.id}/test-message`, { content: args.text }));
|
|
3768
|
+
}
|
|
3769
|
+
case 'test_resolve': {
|
|
3770
|
+
if (!args.id) throw new Error('id is required for action=test_resolve');
|
|
3771
|
+
if (!args.actionId) throw new Error('actionId is required for action=test_resolve');
|
|
3772
|
+
return ok(await api('POST', `/api/collectors/${args.id}/test-resolve`, { actionId: args.actionId, approve: args.approve !== false }));
|
|
3773
|
+
}
|
|
3748
3774
|
default:
|
|
3749
3775
|
throw new Error(`Unknown collector action: ${action}`);
|
|
3750
3776
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "drafted",
|
|
3
|
-
"version": "1.11.
|
|
3
|
+
"version": "1.11.33",
|
|
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": [
|