drafted 1.10.1 → 1.10.2
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 +34 -18
- package/package.json +1 -1
package/mcp/server.mjs
CHANGED
|
@@ -832,6 +832,34 @@ function summarizeSkillForSearch(skill) {
|
|
|
832
832
|
};
|
|
833
833
|
}
|
|
834
834
|
|
|
835
|
+
// Ultra-lean catalog entry for browsing large libraries within an agent's token
|
|
836
|
+
// budget: just enough to recognize a skill and load it by slug. Full
|
|
837
|
+
// description/triggerPatterns are only needed on load.
|
|
838
|
+
function compactSkillEntry(skill) {
|
|
839
|
+
if (!skill || typeof skill !== 'object') return skill;
|
|
840
|
+
return { slug: skill.slug, name: skill.name, tags: skill.tags || [] };
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
// Shape a {skills:[...]} catalog result (search or list) with limit/offset
|
|
844
|
+
// pagination and an optional compact mode, so an 82-entry global catalog stays
|
|
845
|
+
// within an agent's token budget. Mirrors how `search` already caps client-side.
|
|
846
|
+
function shapeSkillCatalog(result, { limit, offset = 0, compact = false } = {}) {
|
|
847
|
+
if (!Array.isArray(result?.skills)) return result;
|
|
848
|
+
const total = result.skills.length;
|
|
849
|
+
const start = Math.max(0, Math.floor(Number(offset) || 0));
|
|
850
|
+
const cap = Math.min(Math.max(1, Math.floor(Number(limit) || 25)), 100);
|
|
851
|
+
const page = result.skills.slice(start, start + cap);
|
|
852
|
+
result.totalAvailable = total;
|
|
853
|
+
result.offset = start;
|
|
854
|
+
result.returned = page.length;
|
|
855
|
+
result.truncated = start + page.length < total;
|
|
856
|
+
result.skills = page.map(compact ? compactSkillEntry : summarizeSkillForSearch);
|
|
857
|
+
result.note = compact
|
|
858
|
+
? 'Compact catalog: {slug,name,tags} only. Load full content with skill(action="load", skill="<slug>"). Pass compact=false for descriptions/triggerPatterns; use offset to page.'
|
|
859
|
+
: 'Search/list returns skill summaries only (no SKILL.md body). Use skill(action="load", skill="<slug-or-id>") for full content. Pass compact=true for a leaner {slug,name,tags} catalog; use limit/offset to page.';
|
|
860
|
+
return result;
|
|
861
|
+
}
|
|
862
|
+
|
|
835
863
|
// Build the structuredContent shape that the frame-preview widget reads.
|
|
836
864
|
// Tools that produce or return a frame (read/write/edit) call this so the
|
|
837
865
|
// model and widget see the same metadata view.
|
|
@@ -2663,7 +2691,9 @@ tool('skill', 'Manage the Drafted skill library. Skills are reusable prompts/gui
|
|
|
2663
2691
|
query: z.string().optional().describe('[search] term to match against name/description/content'),
|
|
2664
2692
|
tags: z.array(z.string()).optional().describe('[search] filter by tags; [add|update] tag list'),
|
|
2665
2693
|
scope: z.enum(['all', 'org', 'global']).optional().describe('[search|list] library scope (default: all for search; when provided to list, lists the library instead of project/org attachments)'),
|
|
2666
|
-
limit: z.number().optional().describe('[search] max results (default 25, max 100)'),
|
|
2694
|
+
limit: z.number().optional().describe('[search|list] max results per page (default 25, max 100)'),
|
|
2695
|
+
offset: z.number().optional().describe('[search|list] skip N results for pagination (default 0). Response reports totalAvailable/returned/truncated.'),
|
|
2696
|
+
compact: z.boolean().optional().describe('[search|list] return only {slug,name,tags} per skill instead of full summaries — for browsing large catalogs within token budget'),
|
|
2667
2697
|
skill: z.string().optional().describe('[load] skill ID (UUID) or slug'),
|
|
2668
2698
|
skillId: z.string().optional().describe('[update|remove|attach|detach|favorite|unfavorite|read_file|update_file] skill ID'),
|
|
2669
2699
|
projectId: z.string().optional().describe('[list] project to list skills for (defaults to active project; falls back to org-attached skills if no project)'),
|
|
@@ -2682,7 +2712,7 @@ tool('skill', 'Manage the Drafted skill library. Skills are reusable prompts/gui
|
|
|
2682
2712
|
const { action } = args;
|
|
2683
2713
|
switch (action) {
|
|
2684
2714
|
case 'search': {
|
|
2685
|
-
const { query, tags, scope = 'all', limit
|
|
2715
|
+
const { query, tags, scope = 'all', limit, offset, compact } = args;
|
|
2686
2716
|
const params = new URLSearchParams();
|
|
2687
2717
|
if (query) params.set('q', query);
|
|
2688
2718
|
if (tags?.length) params.set('tags', tags.join(','));
|
|
@@ -2691,17 +2721,7 @@ tool('skill', 'Manage the Drafted skill library. Skills are reusable prompts/gui
|
|
|
2691
2721
|
const endpoint = query ? '/api/skills/search' : '/api/skills';
|
|
2692
2722
|
const result = await api('GET', `${endpoint}${qs ? '?' + qs : ''}`);
|
|
2693
2723
|
markSearched(getSessionState().gates, 'skill');
|
|
2694
|
-
|
|
2695
|
-
if (Array.isArray(result?.skills)) {
|
|
2696
|
-
if (result.skills.length > cap) {
|
|
2697
|
-
result.totalAvailable = result.skills.length;
|
|
2698
|
-
result.truncated = true;
|
|
2699
|
-
result.skills = result.skills.slice(0, cap);
|
|
2700
|
-
}
|
|
2701
|
-
result.skills = result.skills.map(summarizeSkillForSearch);
|
|
2702
|
-
result.note = 'Search/list returns skill summaries only. Use skill(action="load", skill="<slug-or-id>") to read full SKILL.md content and supporting file list.';
|
|
2703
|
-
}
|
|
2704
|
-
return ok(result);
|
|
2724
|
+
return ok(shapeSkillCatalog(result, { limit, offset, compact }));
|
|
2705
2725
|
}
|
|
2706
2726
|
case 'load': {
|
|
2707
2727
|
const { skill } = args;
|
|
@@ -2718,11 +2738,7 @@ tool('skill', 'Manage the Drafted skill library. Skills are reusable prompts/gui
|
|
|
2718
2738
|
params.set('scope', args.scope || 'all');
|
|
2719
2739
|
if (args.tags?.length) params.set('tags', args.tags.join(','));
|
|
2720
2740
|
const result = await api('GET', `/api/skills?${params.toString()}`);
|
|
2721
|
-
|
|
2722
|
-
result.skills = result.skills.map(summarizeSkillForSearch);
|
|
2723
|
-
result.note = 'Library list returns skill summaries only. Use skill(action="load", skill="<slug-or-id>") to read full SKILL.md content and supporting file list.';
|
|
2724
|
-
}
|
|
2725
|
-
return ok(result);
|
|
2741
|
+
return ok(shapeSkillCatalog(result, { limit: args.limit, offset: args.offset, compact: args.compact }));
|
|
2726
2742
|
}
|
|
2727
2743
|
|
|
2728
2744
|
// Prefer the explicit projectId param; otherwise the active project;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "drafted",
|
|
3
|
-
"version": "1.10.
|
|
3
|
+
"version": "1.10.2",
|
|
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": [
|