drafted 1.5.0 → 1.6.0
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 +24 -15
- package/package.json +1 -1
package/mcp/server.mjs
CHANGED
|
@@ -1545,8 +1545,8 @@ tool('batch', 'Batch operations on the ACTIVE PROJECT. Response includes "projec
|
|
|
1545
1545
|
|
|
1546
1546
|
// ── Asset tools ──────────────────────────────────────────────────
|
|
1547
1547
|
|
|
1548
|
-
tool('asset', 'Manage supporting files (CSS, JS, images, fonts) in the ACTIVE PROJECT. Assets are referenced by frames via relative paths — e.g., if your HTML has <link href="css/styles.css">, upload with asset_path="css/styles.css". Assets are NOT frames — they don\'t appear on the canvas. `action=upload` to add/replace, `action=list` to browse.', {
|
|
1549
|
-
action: z.enum(['upload', 'list']).describe('Operation to perform.'),
|
|
1548
|
+
tool('asset', 'Manage supporting files (CSS, JS, images, fonts) in the ACTIVE PROJECT. Assets are referenced by frames via relative paths — e.g., if your HTML has <link href="css/styles.css">, upload with asset_path="css/styles.css". Assets are NOT frames — they don\'t appear on the canvas. `action=upload` to add/replace, `action=list` to browse, `action=rm` to delete.', {
|
|
1549
|
+
action: z.enum(['upload', 'list', 'rm']).describe('Operation to perform.'),
|
|
1550
1550
|
asset_path: z.string().optional().describe('[upload] relative asset path (e.g. "css/styles.css"). Must match the path used in HTML references.'),
|
|
1551
1551
|
file_path: z.string().optional().describe('[upload] absolute path to a local file. Mutually exclusive with content/base64.'),
|
|
1552
1552
|
content: z.string().optional().describe('[upload] text content (for CSS/JS). Mutually exclusive with file_path/base64.'),
|
|
@@ -1589,6 +1589,14 @@ tool('asset', 'Manage supporting files (CSS, JS, images, fonts) in the ACTIVE PR
|
|
|
1589
1589
|
const query = frame_id ? `?frameId=${frame_id}` : '';
|
|
1590
1590
|
return ok(await api('GET', `/api/projects/${projectId}/assets${query}`));
|
|
1591
1591
|
}
|
|
1592
|
+
if (action === 'rm') {
|
|
1593
|
+
const skillErr = await checkProjectSkills(projectId);
|
|
1594
|
+
if (skillErr) return err(new Error(skillErr));
|
|
1595
|
+
const { asset_path } = args;
|
|
1596
|
+
if (!asset_path) throw new Error('asset_path is required for action=rm');
|
|
1597
|
+
if (asset_path.includes('..')) throw new Error('asset_path must not contain ".."');
|
|
1598
|
+
return ok(await api('DELETE', `/api/projects/${projectId}/assets/${asset_path}`));
|
|
1599
|
+
}
|
|
1592
1600
|
throw new Error(`Unknown asset action: ${action}`);
|
|
1593
1601
|
} catch (error) { return err(error); }
|
|
1594
1602
|
});
|
|
@@ -1960,20 +1968,18 @@ tool('wiki', 'Per-org wiki. Markdown pages with paths as hierarchy. You and othe
|
|
|
1960
1968
|
}
|
|
1961
1969
|
|
|
1962
1970
|
// ── read ────────────────────────────────────────────────────
|
|
1971
|
+
// Returns content in hashline format (`lineNum:hash|content`) so the
|
|
1972
|
+
// agent can produce hashline edit operations. Mirrors frame.read.
|
|
1963
1973
|
case 'read': {
|
|
1964
1974
|
const { path: readPath, lines: readLines } = args;
|
|
1965
1975
|
if (!readPath) throw new Error('path required for action=read');
|
|
1966
1976
|
const normalized = normalizeWikiPath(readPath);
|
|
1967
|
-
const
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
const m = readLines.match(/^(\d+)-(\d+)$/);
|
|
1972
|
-
if (!m) throw new Error(`lines must be "N-M" (e.g. "10-50"), got: ${readLines}`);
|
|
1973
|
-
const [start, end] = [parseInt(m[1]), parseInt(m[2])];
|
|
1974
|
-
const allLines = outContent.split('\n');
|
|
1975
|
-
outContent = allLines.slice(Math.max(0, start - 1), end).join('\n');
|
|
1977
|
+
const params = new URLSearchParams({ path: normalized, format: 'hashline' });
|
|
1978
|
+
if (readLines) {
|
|
1979
|
+
if (!/^\d+-\d+$/.test(readLines)) throw new Error(`lines must be "N-M" (e.g. "10-50"), got: ${readLines}`);
|
|
1980
|
+
params.set('lines', readLines);
|
|
1976
1981
|
}
|
|
1982
|
+
const page = await api('GET', `/api/wiki/page?${params.toString()}`);
|
|
1977
1983
|
// Get backlink count via search (approximate)
|
|
1978
1984
|
let backlinkCount = 0;
|
|
1979
1985
|
try {
|
|
@@ -1985,7 +1991,8 @@ tool('wiki', 'Per-org wiki. Markdown pages with paths as hierarchy. You and othe
|
|
|
1985
1991
|
title: page.title,
|
|
1986
1992
|
type: page.type,
|
|
1987
1993
|
frontmatter: page.frontmatter,
|
|
1988
|
-
content:
|
|
1994
|
+
content: page.content,
|
|
1995
|
+
totalLines: page.totalLines,
|
|
1989
1996
|
lastEditedBy: page.updatedBy,
|
|
1990
1997
|
lastEditedAt: page.updatedAt,
|
|
1991
1998
|
backlinkCount,
|
|
@@ -2069,15 +2076,17 @@ tool('wiki', 'Per-org wiki. Markdown pages with paths as hierarchy. You and othe
|
|
|
2069
2076
|
}
|
|
2070
2077
|
|
|
2071
2078
|
// ── edit ────────────────────────────────────────────────────
|
|
2079
|
+
// Hashlines come from `read` (which now formats content as
|
|
2080
|
+
// `lineNum:hash|content`). The server applies the ops via the same
|
|
2081
|
+
// hashline algorithm — no client-side re-hashing, no algorithm drift.
|
|
2072
2082
|
case 'edit': {
|
|
2073
2083
|
const { path: editPath, operations: editOps } = args;
|
|
2074
2084
|
if (!editPath) throw new Error('path required for action=edit');
|
|
2075
2085
|
if (!Array.isArray(editOps) || editOps.length === 0) throw new Error('operations (array) required for action=edit');
|
|
2076
2086
|
const normalized = normalizeWikiPath(editPath);
|
|
2077
2087
|
const page = await api('GET', `/api/wiki/page?path=${encodeURIComponent(normalized)}`);
|
|
2078
|
-
const
|
|
2079
|
-
|
|
2080
|
-
return ok(withOrg({ path: result.path, id: result.id, updated: true }));
|
|
2088
|
+
const result = await api('POST', `/api/wiki/pages/${page.id}/edit`, { operations: editOps });
|
|
2089
|
+
return ok(withOrg({ path: result.path, id: result.id, updated: true, applied: result.applied }));
|
|
2081
2090
|
}
|
|
2082
2091
|
|
|
2083
2092
|
// ── mv ──────────────────────────────────────────────────────
|