emdash-emit 0.1.8 → 0.1.9
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/README.md +58 -23
- package/dist/cli/commands/profile.d.ts.map +1 -1
- package/dist/cli/commands/profile.js +67 -13
- package/dist/cli/commands/profile.js.map +1 -1
- package/dist/cli/commands/pull.d.ts +5 -0
- package/dist/cli/commands/pull.d.ts.map +1 -1
- package/dist/cli/commands/pull.js +96 -39
- package/dist/cli/commands/pull.js.map +1 -1
- package/dist/cli/commands/push.d.ts.map +1 -1
- package/dist/cli/commands/push.js +16 -1
- package/dist/cli/commands/push.js.map +1 -1
- package/dist/cli/commands/status.d.ts +19 -0
- package/dist/cli/commands/status.d.ts.map +1 -1
- package/dist/cli/commands/status.js +69 -3
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/context.d.ts +35 -0
- package/dist/cli/context.d.ts.map +1 -1
- package/dist/cli/context.js +112 -10
- package/dist/cli/context.js.map +1 -1
- package/dist/client/auth.d.ts +1 -0
- package/dist/client/auth.d.ts.map +1 -1
- package/dist/client/auth.js +1 -0
- package/dist/client/auth.js.map +1 -1
- package/dist/client/http.d.ts.map +1 -1
- package/dist/client/http.js +27 -10
- package/dist/client/http.js.map +1 -1
- package/dist/mcp/context.d.ts +1 -0
- package/dist/mcp/context.d.ts.map +1 -1
- package/dist/mcp/server.d.ts +8 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +52 -13
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tool-errors.d.ts +11 -0
- package/dist/mcp/tool-errors.d.ts.map +1 -0
- package/dist/mcp/tool-errors.js +62 -0
- package/dist/mcp/tool-errors.js.map +1 -0
- package/dist/mcp/tools/profile.d.ts +9 -2
- package/dist/mcp/tools/profile.d.ts.map +1 -1
- package/dist/mcp/tools/profile.js +49 -36
- package/dist/mcp/tools/profile.js.map +1 -1
- package/dist/mcp/tools/sync-diff.d.ts.map +1 -1
- package/dist/mcp/tools/sync-diff.js +20 -7
- package/dist/mcp/tools/sync-diff.js.map +1 -1
- package/dist/mcp/tools/sync-new.d.ts.map +1 -1
- package/dist/mcp/tools/sync-new.js +35 -22
- package/dist/mcp/tools/sync-new.js.map +1 -1
- package/dist/mcp/tools/sync-pull.d.ts.map +1 -1
- package/dist/mcp/tools/sync-pull.js +101 -72
- package/dist/mcp/tools/sync-pull.js.map +1 -1
- package/dist/mcp/tools/sync-push.d.ts.map +1 -1
- package/dist/mcp/tools/sync-push.js +24 -32
- package/dist/mcp/tools/sync-push.js.map +1 -1
- package/dist/mcp/tools/sync-status.d.ts.map +1 -1
- package/dist/mcp/tools/sync-status.js +55 -4
- package/dist/mcp/tools/sync-status.js.map +1 -1
- package/dist/sync/orchestrator.d.ts +6 -0
- package/dist/sync/orchestrator.d.ts.map +1 -1
- package/dist/sync/orchestrator.js +52 -27
- package/dist/sync/orchestrator.js.map +1 -1
- package/dist/sync/pull.d.ts +47 -0
- package/dist/sync/pull.d.ts.map +1 -1
- package/dist/sync/pull.js +148 -8
- package/dist/sync/pull.js.map +1 -1
- package/dist/sync/push.d.ts +2 -0
- package/dist/sync/push.d.ts.map +1 -1
- package/dist/sync/push.js +30 -3
- package/dist/sync/push.js.map +1 -1
- package/dist/sync/status.d.ts +11 -1
- package/dist/sync/status.d.ts.map +1 -1
- package/dist/sync/status.js +40 -6
- package/dist/sync/status.js.map +1 -1
- package/dist/sync/taxonomies.d.ts.map +1 -1
- package/dist/sync/taxonomies.js +39 -4
- package/dist/sync/taxonomies.js.map +1 -1
- package/dist/utils/config.d.ts +11 -0
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +14 -4
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/frontmatter.d.ts +13 -1
- package/dist/utils/frontmatter.d.ts.map +1 -1
- package/dist/utils/frontmatter.js +49 -7
- package/dist/utils/frontmatter.js.map +1 -1
- package/dist/utils/profile.d.ts +3 -3
- package/dist/utils/profile.d.ts.map +1 -1
- package/dist/utils/profile.js +105 -8
- package/dist/utils/profile.js.map +1 -1
- package/package.json +1 -1
|
@@ -20,12 +20,13 @@
|
|
|
20
20
|
* SOFTWARE.
|
|
21
21
|
*/
|
|
22
22
|
import { z } from 'zod';
|
|
23
|
-
import { pullArticle } from '../../sync/pull.js';
|
|
24
|
-
import { pullBatch
|
|
23
|
+
import { pullArticle, formatQuarantineNotice } from '../../sync/pull.js';
|
|
24
|
+
import { pullBatch } from '../../sync/orchestrator.js';
|
|
25
25
|
import { pullTaxonomies, getLocalTaxonomiesSummary, formatTaxonomiesHint, } from '../../sync/taxonomies.js';
|
|
26
26
|
import { pullMedia } from '../../sync/media.js';
|
|
27
27
|
import { resolveArticleTarget } from '../../sync/diff.js';
|
|
28
28
|
import { compareArticleFilenameDesc } from '../../utils/naming.js';
|
|
29
|
+
import { formatToolError } from '../tool-errors.js';
|
|
29
30
|
export function registerSyncPullTools(server, resolveContext) {
|
|
30
31
|
// sync_pull: Pull remote article(s) and taxonomies
|
|
31
32
|
server.tool('sync_pull', 'Pull remote articles and taxonomies from EmDash into local Markdown files (posts/published/ and posts/draft/) and YAML taxonomy definitions (categories/ and tags/). Batch mode automatically syncs categories and tags alongside articles and returns available taxonomy hints (also shown with postsOnly:true). Use postsOnly:true to skip taxonomies. Use includeMedia:true to also pull media assets. Supports pulling a single article by id/filePath. After pulling, ALWAYS read and edit the local Markdown files directly with standard file tools.', {
|
|
@@ -65,7 +66,13 @@ export function registerSyncPullTools(server, resolveContext) {
|
|
|
65
66
|
.describe('With includeMedia: download only metadata YAML, skip binary file downloads.'),
|
|
66
67
|
profile: z.string().optional().describe('Target profile name for multi-site setups'),
|
|
67
68
|
}, async (args) => {
|
|
68
|
-
|
|
69
|
+
let ctx;
|
|
70
|
+
try {
|
|
71
|
+
ctx = resolveContext(args.profile);
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
return formatToolError(error);
|
|
75
|
+
}
|
|
69
76
|
const collection = args.collection || ctx.config.defaultCollection;
|
|
70
77
|
const origin = ctx.origin;
|
|
71
78
|
const { id: targetId } = resolveArticleTarget({
|
|
@@ -74,23 +81,38 @@ export function registerSyncPullTools(server, resolveContext) {
|
|
|
74
81
|
id: args.id,
|
|
75
82
|
});
|
|
76
83
|
if (targetId) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
84
|
+
let res;
|
|
85
|
+
try {
|
|
86
|
+
res = await pullArticle(collection, targetId, {
|
|
87
|
+
workspaceRoot: ctx.root,
|
|
88
|
+
cache: ctx.cache,
|
|
89
|
+
origin,
|
|
90
|
+
token: ctx.auth.token,
|
|
91
|
+
refreshToken: ctx.auth.refreshToken,
|
|
92
|
+
force: args.force,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
return formatToolError(error);
|
|
97
|
+
}
|
|
98
|
+
const actionText = res.localEditsPreserved
|
|
99
|
+
? 'ℹ️ Local edits preserved (remote changes were NOT applied)'
|
|
100
|
+
: res.skipped
|
|
101
|
+
? 'ℹ️ Article is already up-to-date'
|
|
102
|
+
: '✅ Successfully pulled article';
|
|
88
103
|
const titleText = res.title ? ` "${res.title}"` : '';
|
|
104
|
+
const warnLine = ctx.originWarning ? `\n\n${ctx.originWarning}` : '';
|
|
105
|
+
const quarantineNotice = formatQuarantineNotice(res.quarantined);
|
|
106
|
+
const quarantineLine = quarantineNotice ? `\n\n${quarantineNotice}` : '';
|
|
107
|
+
const nextStep = res.localEditsPreserved
|
|
108
|
+
? '\n\nYour local version is intact. Push it with sync_push to publish your edits, ' +
|
|
109
|
+
'or re-run sync_pull with force: true to accept the remote version instead.'
|
|
110
|
+
: '\n\nYou can now read or edit this local Markdown file directly.';
|
|
89
111
|
return {
|
|
90
112
|
content: [
|
|
91
113
|
{
|
|
92
114
|
type: 'text',
|
|
93
|
-
text: `${actionText}${titleText} (${res.slug})\nFile path: ${res.filePath}\nStatus: ${res.status}
|
|
115
|
+
text: `${actionText}${titleText} (${res.slug})\nFile path: ${res.filePath}\nStatus: ${res.status}${quarantineLine}${warnLine}${nextStep}`,
|
|
94
116
|
},
|
|
95
117
|
],
|
|
96
118
|
};
|
|
@@ -148,6 +170,13 @@ export function registerSyncPullTools(server, resolveContext) {
|
|
|
148
170
|
const listLines = sampleItems.map((item) => ` - [${item.status}] ${item.filePath}${item.title ? ` (${item.title})` : ''}`);
|
|
149
171
|
const headerLabel = updatedItems.length > 0 ? 'Updated Articles' : 'Recent Articles in Workspace';
|
|
150
172
|
const detailBlock = listLines.length > 0 ? `\n\n${headerLabel}:\n${listLines.join('\n')}` : '';
|
|
173
|
+
const preservedMsg = batchResult.preserved && batchResult.preserved > 0
|
|
174
|
+
? `\n🛡️ ${batchResult.preserved} article(s) had unpushed local edits; Emit kept your local version (remote changes were NOT applied). Push them with sync_push, or re-run with force: true to accept the remote version instead.`
|
|
175
|
+
: '';
|
|
176
|
+
const quarantineNotices = sortedItems
|
|
177
|
+
.map((item) => formatQuarantineNotice(item.quarantined))
|
|
178
|
+
.filter((notice) => notice.length > 0);
|
|
179
|
+
const quarantineMsg = quarantineNotices.length > 0 ? `\n\n${quarantineNotices.join('\n\n')}` : '';
|
|
151
180
|
// 3. Pull media if includeMedia
|
|
152
181
|
let mediaMsg = '';
|
|
153
182
|
if (includeMedia) {
|
|
@@ -162,60 +191,55 @@ export function registerSyncPullTools(server, resolveContext) {
|
|
|
162
191
|
});
|
|
163
192
|
mediaMsg = `\nMedia: ${mediaResult.total} items (${mediaResult.downloaded} downloaded, ${mediaResult.skipped} up-to-date).`;
|
|
164
193
|
}
|
|
194
|
+
const warnLine = ctx.originWarning ? `\n\n${ctx.originWarning}` : '';
|
|
165
195
|
return {
|
|
166
196
|
content: [
|
|
167
197
|
{
|
|
168
198
|
type: 'text',
|
|
169
|
-
text: `✅ Synced ${batchResult.total} articles (${batchResult.updated} updated, ${batchResult.skipped} up-to-date/skipped${deletedMsg}).${taxonomiesMsg}${mediaMsg}${detailBlock}\n\nYou can now read or edit these local Markdown files directly.`,
|
|
199
|
+
text: `✅ Synced ${batchResult.total} articles (${batchResult.updated} updated, ${batchResult.skipped} up-to-date/skipped${deletedMsg}).${taxonomiesMsg}${mediaMsg}${preservedMsg}${quarantineMsg}${detailBlock}${warnLine}\n\nYou can now read or edit these local Markdown files directly.`,
|
|
170
200
|
},
|
|
171
201
|
],
|
|
172
202
|
};
|
|
173
203
|
}
|
|
174
204
|
catch (error) {
|
|
175
|
-
|
|
176
|
-
return {
|
|
177
|
-
isError: true,
|
|
178
|
-
content: [
|
|
179
|
-
{
|
|
180
|
-
type: 'text',
|
|
181
|
-
text: `❌ ${error.message}`,
|
|
182
|
-
},
|
|
183
|
-
],
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
throw error;
|
|
205
|
+
return formatToolError(error);
|
|
187
206
|
}
|
|
188
207
|
});
|
|
189
208
|
// sync_pull_taxonomies
|
|
190
209
|
server.tool('sync_pull_taxonomies', 'Pull remote categories and tags into local YAML definitions (categories/<id>-<name>.yaml and tags/<id>-<name>.yaml) and return formatted available categories/tags hints (up to 200 tags). Use before writing articles to inspect valid category and tag IDs/slugs.', {
|
|
191
210
|
profile: z.string().optional().describe('Target profile name for multi-site setups'),
|
|
192
211
|
}, async (args) => {
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
212
|
+
try {
|
|
213
|
+
const ctx = resolveContext(args.profile);
|
|
214
|
+
const res = await pullTaxonomies({
|
|
215
|
+
workspaceRoot: ctx.root,
|
|
216
|
+
origin: ctx.origin,
|
|
217
|
+
token: ctx.auth.token,
|
|
218
|
+
refreshToken: ctx.auth.refreshToken,
|
|
219
|
+
});
|
|
220
|
+
const taxSummary = getLocalTaxonomiesSummary(ctx.root);
|
|
221
|
+
const taxHint = formatTaxonomiesHint(taxSummary, { maxTags: 200 });
|
|
222
|
+
const hintBlock = taxHint ? `\n\n${taxHint}` : '';
|
|
223
|
+
const failNotes = [];
|
|
224
|
+
if (res.categoriesFailed)
|
|
225
|
+
failNotes.push('categories');
|
|
226
|
+
if (res.tagsFailed)
|
|
227
|
+
failNotes.push('tags');
|
|
228
|
+
const statusLine = failNotes.length > 0
|
|
229
|
+
? `⚠️ Warning: Failed to fetch remote ${failNotes.join(' and ')} (preserved existing local definitions in categories/ and tags/).`
|
|
230
|
+
: `✅ Successfully pulled taxonomies (${res.categoriesCount} categories, ${res.tagsCount} tags) into categories/ and tags/.`;
|
|
231
|
+
return {
|
|
232
|
+
content: [
|
|
233
|
+
{
|
|
234
|
+
type: 'text',
|
|
235
|
+
text: `${statusLine}${hintBlock}`,
|
|
236
|
+
},
|
|
237
|
+
],
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
catch (error) {
|
|
241
|
+
return formatToolError(error);
|
|
242
|
+
}
|
|
219
243
|
});
|
|
220
244
|
// sync_pull_media
|
|
221
245
|
server.tool('sync_pull_media', 'Download remote media assets and companion YAML metadata into the local media/ directory (media/<yyyyMMdd>_<id>-<name>.<ext> and .yaml). Enables offline browsing and referencing of uploaded images.', {
|
|
@@ -227,24 +251,29 @@ export function registerSyncPullTools(server, resolveContext) {
|
|
|
227
251
|
downloadFiles: z.boolean().optional().describe('Download binary files (defaults to true)'),
|
|
228
252
|
profile: z.string().optional().describe('Target profile name for multi-site setups'),
|
|
229
253
|
}, async (args) => {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
254
|
+
try {
|
|
255
|
+
const ctx = resolveContext(args.profile);
|
|
256
|
+
const res = await pullMedia({
|
|
257
|
+
workspaceRoot: ctx.root,
|
|
258
|
+
origin: ctx.origin,
|
|
259
|
+
token: ctx.auth.token,
|
|
260
|
+
refreshToken: ctx.auth.refreshToken,
|
|
261
|
+
limit: args.limit || ctx.config.mediaSyncLimit || 300,
|
|
262
|
+
all: args.all,
|
|
263
|
+
downloadFiles: args.downloadFiles,
|
|
264
|
+
});
|
|
265
|
+
return {
|
|
266
|
+
content: [
|
|
267
|
+
{
|
|
268
|
+
type: 'text',
|
|
269
|
+
text: `✅ Successfully pulled media: ${res.total} items (${res.downloaded} downloaded, ${res.skipped} skipped/up-to-date).`,
|
|
270
|
+
},
|
|
271
|
+
],
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
catch (error) {
|
|
275
|
+
return formatToolError(error);
|
|
276
|
+
}
|
|
248
277
|
});
|
|
249
278
|
}
|
|
250
279
|
//# sourceMappingURL=sync-pull.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync-pull.js","sourceRoot":"","sources":["../../../src/mcp/tools/sync-pull.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"sync-pull.js","sourceRoot":"","sources":["../../../src/mcp/tools/sync-pull.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,WAAW,EAAE,sBAAsB,EAAmB,MAAM,oBAAoB,CAAC;AAC1F,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,EACL,cAAc,EACd,yBAAyB,EACzB,oBAAoB,GACrB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,UAAU,qBAAqB,CAAC,MAAiB,EAAE,cAA+B;IACtF,mDAAmD;IACnD,MAAM,CAAC,IAAI,CACT,WAAW,EACX,6hBAA6hB,EAC7hB;QACE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,+CAA+C,CAAC;QAC3F,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6BAA6B,CAAC;QACjE,QAAQ,EAAE,CAAC;aACR,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,iEAAiE,CAAC;QAC9E,MAAM,EAAE,CAAC;aACN,IAAI,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;aACnC,QAAQ,EAAE;aACV,QAAQ,CAAC,2DAA2D,CAAC;QACxE,KAAK,EAAE,CAAC;aACL,OAAO,EAAE;aACT,QAAQ,EAAE;aACV,QAAQ,CAAC,mEAAmE,CAAC;QAChF,OAAO,EAAE,CAAC;aACP,OAAO,EAAE;aACT,QAAQ,EAAE;aACV,QAAQ,CACP,gGAAgG,CACjG;QACH,KAAK,EAAE,CAAC;aACL,OAAO,EAAE;aACT,QAAQ,EAAE;aACV,QAAQ,CAAC,sEAAsE,CAAC;QACnF,SAAS,EAAE,CAAC;aACT,OAAO,EAAE;aACT,QAAQ,EAAE;aACV,QAAQ,CAAC,2DAA2D,CAAC;QACxE,YAAY,EAAE,CAAC;aACZ,OAAO,EAAE;aACT,QAAQ,EAAE;aACV,QAAQ,CAAC,4DAA4D,CAAC;QACzE,YAAY,EAAE,CAAC;aACZ,OAAO,EAAE;aACT,QAAQ,EAAE;aACV,QAAQ,CAAC,6EAA6E,CAAC;QAC1F,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,2CAA2C,CAAC;KACrF,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,IAAI,GAAkB,CAAC;QACvB,IAAI,CAAC;YACH,GAAG,GAAG,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACrC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;QACD,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,GAAG,CAAC,MAAM,CAAC,iBAAiB,CAAC;QACnE,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;QAE1B,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,GAAG,oBAAoB,CAAC;YAC5C,aAAa,EAAE,GAAG,CAAC,IAAI;YACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,EAAE,EAAE,IAAI,CAAC,EAAE;SACZ,CAAC,CAAC;QAEH,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,GAAe,CAAC;YACpB,IAAI,CAAC;gBACH,GAAG,GAAG,MAAM,WAAW,CAAC,UAAU,EAAE,QAAQ,EAAE;oBAC5C,aAAa,EAAE,GAAG,CAAC,IAAI;oBACvB,KAAK,EAAE,GAAG,CAAC,KAAK;oBAChB,MAAM;oBACN,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK;oBACrB,YAAY,EAAE,GAAG,CAAC,IAAI,CAAC,YAAY;oBACnC,KAAK,EAAE,IAAI,CAAC,KAAK;iBAClB,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;YAChC,CAAC;YAED,MAAM,UAAU,GAAG,GAAG,CAAC,mBAAmB;gBACxC,CAAC,CAAC,4DAA4D;gBAC9D,CAAC,CAAC,GAAG,CAAC,OAAO;oBACX,CAAC,CAAC,kCAAkC;oBACpC,CAAC,CAAC,+BAA+B,CAAC;YACtC,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YACrD,MAAM,QAAQ,GAAG,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACrE,MAAM,gBAAgB,GAAG,sBAAsB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YACjE,MAAM,cAAc,GAAG,gBAAgB,CAAC,CAAC,CAAC,OAAO,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACzE,MAAM,QAAQ,GAAG,GAAG,CAAC,mBAAmB;gBACtC,CAAC,CAAC,kFAAkF;oBAClF,4EAA4E;gBAC9E,CAAC,CAAC,iEAAiE,CAAC;YAEtE,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,GAAG,UAAU,GAAG,SAAS,KAAK,GAAG,CAAC,IAAI,iBAAiB,GAAG,CAAC,QAAQ,aAAa,GAAG,CAAC,MAAM,GAAG,cAAc,GAAG,QAAQ,GAAG,QAAQ,EAAE;qBAC1I;iBACF;aACF,CAAC;QACJ,CAAC;QAED,mEAAmE;QACnE,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,cAAc,IAAI,GAAG,CAAC,MAAM,CAAC,SAAS,IAAI,GAAG,CAAC;QACvE,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;QAC7F,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,KAAK,IAAI,CAAC;QAC1C,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,KAAK,IAAI,CAAC;QAEhD,IAAI,CAAC;YACH,+DAA+D;YAC/D,IAAI,aAAa,GAAG,EAAE,CAAC;YACvB,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,MAAM,SAAS,GAAG,MAAM,cAAc,CAAC;oBACrC,aAAa,EAAE,GAAG,CAAC,IAAI;oBACvB,MAAM;oBACN,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK;oBACrB,YAAY,EAAE,GAAG,CAAC,IAAI,CAAC,YAAY;iBACpC,CAAC,CAAC;gBACH,MAAM,SAAS,GAAa,EAAE,CAAC;gBAC/B,IAAI,SAAS,CAAC,gBAAgB;oBAAE,SAAS,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;gBAC7D,IAAI,SAAS,CAAC,UAAU;oBAAE,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBACjD,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACzB,aAAa,GAAG,2CAA2C,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,0CAA0C,CAAC;gBAC/H,CAAC;qBAAM,CAAC;oBACN,aAAa,GAAG,iBAAiB,SAAS,CAAC,eAAe,gBAAgB,SAAS,CAAC,SAAS,eAAe,CAAC;gBAC/G,CAAC;YACH,CAAC;YAED,MAAM,UAAU,GAAG,yBAAyB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACvD,MAAM,OAAO,GAAG,oBAAoB,CAAC,UAAU,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;YAClE,IAAI,OAAO,EAAE,CAAC;gBACZ,aAAa,IAAI,OAAO,OAAO,EAAE,CAAC;YACpC,CAAC;YAED,mBAAmB;YACnB,MAAM,WAAW,GAAG,MAAM,SAAS,CAAC;gBAClC,UAAU;gBACV,aAAa,EAAE,GAAG,CAAC,IAAI;gBACvB,KAAK,EAAE,GAAG,CAAC,KAAK;gBAChB,MAAM;gBACN,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK;gBACrB,YAAY,EAAE,GAAG,CAAC,IAAI,CAAC,YAAY;gBACnC,KAAK;gBACL,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,KAAK,EAAE,WAAW;aACnB,CAAC,CAAC;YAEH,MAAM,UAAU,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,WAAW,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;YAChF,8FAA8F;YAC9F,MAAM,WAAW,GAAG,CAAC,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACvD,0BAA0B,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,CACnD,CAAC;YACF,MAAM,YAAY,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;YAC1D,MAAM,WAAW,GAAG,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACxF,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,CAC/B,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACzF,CAAC;YACF,MAAM,WAAW,GACf,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,8BAA8B,CAAC;YAChF,MAAM,WAAW,GACf,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,WAAW,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAE7E,MAAM,YAAY,GAChB,WAAW,CAAC,SAAS,IAAI,WAAW,CAAC,SAAS,GAAG,CAAC;gBAChD,CAAC,CAAC,SAAS,WAAW,CAAC,SAAS,kMAAkM;gBAClO,CAAC,CAAC,EAAE,CAAC;YAET,MAAM,iBAAiB,GAAG,WAAW;iBAClC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,sBAAsB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;iBACvD,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YACzC,MAAM,aAAa,GACjB,iBAAiB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAE9E,gCAAgC;YAChC,IAAI,QAAQ,GAAG,EAAE,CAAC;YAClB,IAAI,YAAY,EAAE,CAAC;gBACjB,MAAM,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC,cAAc,IAAI,GAAG,CAAC;gBACpD,MAAM,WAAW,GAAG,MAAM,SAAS,CAAC;oBAClC,aAAa,EAAE,GAAG,CAAC,IAAI;oBACvB,MAAM;oBACN,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK;oBACrB,YAAY,EAAE,GAAG,CAAC,IAAI,CAAC,YAAY;oBACnC,KAAK,EAAE,UAAU;oBACjB,aAAa,EAAE,IAAI,CAAC,YAAY,KAAK,IAAI;iBAC1C,CAAC,CAAC;gBACH,QAAQ,GAAG,YAAY,WAAW,CAAC,KAAK,WAAW,WAAW,CAAC,UAAU,gBAAgB,WAAW,CAAC,OAAO,eAAe,CAAC;YAC9H,CAAC;YAED,MAAM,QAAQ,GAAG,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACrE,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,YAAY,WAAW,CAAC,KAAK,cAAc,WAAW,CAAC,OAAO,aAAa,WAAW,CAAC,OAAO,sBAAsB,UAAU,KAAK,aAAa,GAAG,QAAQ,GAAG,YAAY,GAAG,aAAa,GAAG,WAAW,GAAG,QAAQ,mEAAmE;qBAC7R;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;IACH,CAAC,CACF,CAAC;IAEF,uBAAuB;IACvB,MAAM,CAAC,IAAI,CACT,sBAAsB,EACtB,qQAAqQ,EACrQ;QACE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,2CAA2C,CAAC;KACrF,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACzC,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC;gBAC/B,aAAa,EAAE,GAAG,CAAC,IAAI;gBACvB,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK;gBACrB,YAAY,EAAE,GAAG,CAAC,IAAI,CAAC,YAAY;aACpC,CAAC,CAAC;YAEH,MAAM,UAAU,GAAG,yBAAyB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACvD,MAAM,OAAO,GAAG,oBAAoB,CAAC,UAAU,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;YACnE,MAAM,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,OAAO,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAElD,MAAM,SAAS,GAAa,EAAE,CAAC;YAC/B,IAAI,GAAG,CAAC,gBAAgB;gBAAE,SAAS,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACvD,IAAI,GAAG,CAAC,UAAU;gBAAE,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC3C,MAAM,UAAU,GACd,SAAS,CAAC,MAAM,GAAG,CAAC;gBAClB,CAAC,CAAC,sCAAsC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,mEAAmE;gBAClI,CAAC,CAAC,qCAAqC,GAAG,CAAC,eAAe,gBAAgB,GAAG,CAAC,SAAS,oCAAoC,CAAC;YAEhI,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,GAAG,UAAU,GAAG,SAAS,EAAE;qBAClC;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;IACH,CAAC,CACF,CAAC;IAEF,kBAAkB;IAClB,MAAM,CAAC,IAAI,CACT,iBAAiB,EACjB,uMAAuM,EACvM;QACE,KAAK,EAAE,CAAC;aACL,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,yDAAyD,CAAC;QACtE,GAAG,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,sDAAsD,CAAC;QAC5F,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,0CAA0C,CAAC;QAC1F,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,2CAA2C,CAAC;KACrF,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACzC,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC;gBAC1B,aAAa,EAAE,GAAG,CAAC,IAAI;gBACvB,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK;gBACrB,YAAY,EAAE,GAAG,CAAC,IAAI,CAAC,YAAY;gBACnC,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,GAAG,CAAC,MAAM,CAAC,cAAc,IAAI,GAAG;gBACrD,GAAG,EAAE,IAAI,CAAC,GAAG;gBACb,aAAa,EAAE,IAAI,CAAC,aAAa;aAClC,CAAC,CAAC;YAEH,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,gCAAgC,GAAG,CAAC,KAAK,WAAW,GAAG,CAAC,UAAU,gBAAgB,GAAG,CAAC,OAAO,uBAAuB;qBAC3H;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync-push.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/sync-push.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"sync-push.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/sync-push.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,eAAe,EAAiB,MAAM,eAAe,CAAC;AAIpE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,eAAe,GAAG,IAAI,CAsF7F"}
|
|
@@ -20,10 +20,10 @@
|
|
|
20
20
|
* SOFTWARE.
|
|
21
21
|
*/
|
|
22
22
|
import { z } from 'zod';
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
23
|
+
import { pushArticle } from '../../sync/push.js';
|
|
24
|
+
import { formatToolError } from '../tool-errors.js';
|
|
25
25
|
export function registerSyncPushTool(server, resolveContext) {
|
|
26
|
-
server.tool('sync_push', 'Push local Markdown article modifications or new articles to remote EmDash CMS. Automatically uploads standalone draft images in media/drafts/<file>, rewrites body URLs to /_emdash/api/media/file/<storageKey>, and promotes files to media/. Performs 3-way merge to protect remote edits. Requires allowPublish=true when transitioning status from draft to published. If conflict markers are inserted, resolve them locally before re-pushing.', {
|
|
26
|
+
server.tool('sync_push', 'Push local Markdown article modifications or new articles to remote EmDash CMS. Automatically uploads standalone draft images in media/drafts/<file>, rewrites body URLs to /_emdash/api/media/file/<storageKey>, and promotes files to media/. Performs 3-way merge to protect remote edits. Requires allowPublish=true when transitioning status from draft to published. If conflict markers are inserted, resolve them locally before re-pushing. Paths under posts/conflicts/ are preserved rescue copies and are refused with QUARANTINED_COPY_NOT_PUSHABLE: merge their content into the canonical article first.', {
|
|
27
27
|
filePath: z
|
|
28
28
|
.string()
|
|
29
29
|
.describe('Target markdown file path relative to workspace root (e.g. "posts/draft/20261103_01...-my-article.md")'),
|
|
@@ -33,7 +33,13 @@ export function registerSyncPushTool(server, resolveContext) {
|
|
|
33
33
|
.describe('Explicit confirmation required to change status from draft to published'),
|
|
34
34
|
profile: z.string().optional().describe('Target profile name for multi-site setups'),
|
|
35
35
|
}, async (args) => {
|
|
36
|
-
|
|
36
|
+
let ctx;
|
|
37
|
+
try {
|
|
38
|
+
ctx = resolveContext(args.profile);
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
return formatToolError(err);
|
|
42
|
+
}
|
|
37
43
|
const origin = ctx.origin;
|
|
38
44
|
try {
|
|
39
45
|
const res = await pushArticle(args.filePath, {
|
|
@@ -58,15 +64,25 @@ export function registerSyncPushTool(server, resolveContext) {
|
|
|
58
64
|
],
|
|
59
65
|
};
|
|
60
66
|
}
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
:
|
|
67
|
+
const transitionLines = [];
|
|
68
|
+
if (res.previousId) {
|
|
69
|
+
transitionLines.push(`🆔 Server assigned canonical ULID: '${res.previousId}' -> '${res.id}'.`);
|
|
70
|
+
}
|
|
71
|
+
if (res.previousFilePath) {
|
|
72
|
+
transitionLines.push(`📄 Local file renamed: "${res.previousFilePath}" -> "${res.filePath}" (use the new path for subsequent edits/pushes).`);
|
|
73
|
+
}
|
|
74
|
+
const allWarnings = [
|
|
75
|
+
...(ctx.originWarning ? [ctx.originWarning] : []),
|
|
76
|
+
...(res.warnings || []),
|
|
77
|
+
];
|
|
78
|
+
const warningLines = allWarnings.length > 0 ? ['', '⚠️ Warnings:', ...allWarnings.map((w) => ` - ${w}`)] : [];
|
|
64
79
|
return {
|
|
65
80
|
content: [
|
|
66
81
|
{
|
|
67
82
|
type: 'text',
|
|
68
83
|
text: [
|
|
69
84
|
`✅ Successfully pushed '${res.id}' to remote (${res.filePath}, rev: ${res.rev}).`,
|
|
85
|
+
...transitionLines,
|
|
70
86
|
...warningLines,
|
|
71
87
|
].join('\n'),
|
|
72
88
|
},
|
|
@@ -74,31 +90,7 @@ export function registerSyncPushTool(server, resolveContext) {
|
|
|
74
90
|
};
|
|
75
91
|
}
|
|
76
92
|
catch (err) {
|
|
77
|
-
|
|
78
|
-
return {
|
|
79
|
-
content: [
|
|
80
|
-
{
|
|
81
|
-
type: 'text',
|
|
82
|
-
text: JSON.stringify({
|
|
83
|
-
error: 'PREFLIGHT_VALIDATION_FAILED',
|
|
84
|
-
message: err.message,
|
|
85
|
-
errors: err.errors,
|
|
86
|
-
}, null, 2),
|
|
87
|
-
},
|
|
88
|
-
],
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
if (err instanceof ApiError) {
|
|
92
|
-
return {
|
|
93
|
-
content: [
|
|
94
|
-
{
|
|
95
|
-
type: 'text',
|
|
96
|
-
text: err.toActionableString(),
|
|
97
|
-
},
|
|
98
|
-
],
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
throw err;
|
|
93
|
+
return formatToolError(err);
|
|
102
94
|
}
|
|
103
95
|
});
|
|
104
96
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync-push.js","sourceRoot":"","sources":["../../../src/mcp/tools/sync-push.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"sync-push.js","sourceRoot":"","sources":["../../../src/mcp/tools/sync-push.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync-status.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/sync-status.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"sync-status.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/sync-status.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,eAAe,EAAiB,MAAM,eAAe,CAAC;AAMpE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,eAAe,GAAG,IAAI,CA+E/F"}
|
|
@@ -21,22 +21,73 @@
|
|
|
21
21
|
*/
|
|
22
22
|
import { z } from 'zod';
|
|
23
23
|
import { getWorkspaceStatus } from '../../sync/status.js';
|
|
24
|
+
import { formatToolError } from '../tool-errors.js';
|
|
25
|
+
const MAX_INVALID_MCP_ITEMS = 10;
|
|
24
26
|
export function registerSyncStatusTool(server, resolveContext) {
|
|
25
|
-
server.tool('sync_status', 'Inspect local workspace sync status. Returns all tracked articles sorted newest-first (descending by date), with relative file paths (e.g. posts/published/YYYYMMDD_<id>-<title>.md), publication status (draft/published), and modification state (synced/modified/untracked). ALWAYS use this tool first to locate local files instead of querying remote APIs.', {
|
|
27
|
+
server.tool('sync_status', 'Inspect local workspace sync status. Returns all tracked articles sorted newest-first (descending by date), with relative file paths (e.g. posts/published/YYYYMMDD_<id>-<title>.md), publication status (draft/published), and modification state (synced/modified/untracked/invalid). ALWAYS use this tool first to locate local files instead of querying remote APIs.', {
|
|
26
28
|
collection: z
|
|
27
29
|
.string()
|
|
28
30
|
.optional()
|
|
29
31
|
.describe('Collection name to inspect (defaults to "posts")'),
|
|
30
32
|
profile: z.string().optional().describe('Target profile name for multi-site setups'),
|
|
31
33
|
}, async (args) => {
|
|
32
|
-
|
|
34
|
+
// Resolve context inside the guard too: workspace/profile resolution can throw
|
|
35
|
+
// AmbiguousProfileError or "Not inside an Emit workspace", and agents need those
|
|
36
|
+
// formatted the same way as every other tool failure.
|
|
37
|
+
let ctx;
|
|
38
|
+
try {
|
|
39
|
+
ctx = resolveContext(args.profile);
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
return formatToolError(error);
|
|
43
|
+
}
|
|
33
44
|
const collection = args.collection || ctx.config.defaultCollection;
|
|
34
|
-
|
|
45
|
+
let status;
|
|
46
|
+
try {
|
|
47
|
+
status = getWorkspaceStatus(ctx.root, ctx.cache, collection);
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
return formatToolError(error);
|
|
51
|
+
}
|
|
52
|
+
// Cap invalid items in MCP output to prevent context window flooding when many files are broken
|
|
53
|
+
let invalidSeen = 0;
|
|
54
|
+
const filteredItems = status.items.filter((item) => {
|
|
55
|
+
if (item.syncStatus !== 'invalid')
|
|
56
|
+
return true;
|
|
57
|
+
invalidSeen++;
|
|
58
|
+
return invalidSeen <= MAX_INVALID_MCP_ITEMS;
|
|
59
|
+
});
|
|
60
|
+
const invalidTruncated = Math.max(0, status.summary.invalid - MAX_INVALID_MCP_ITEMS);
|
|
61
|
+
const uncachedInvalid = status.items.filter((item) => item.syncStatus === 'invalid' && item.cached === false);
|
|
62
|
+
const exampleUncachedId = uncachedInvalid.find((i) => i.id && i.id !== 'unknown')?.id || '<ULID>';
|
|
63
|
+
const responsePayload = {
|
|
64
|
+
items: filteredItems,
|
|
65
|
+
summary: status.summary,
|
|
66
|
+
...(ctx.originWarning ? { warnings: [ctx.originWarning] } : {}),
|
|
67
|
+
...(invalidTruncated > 0
|
|
68
|
+
? {
|
|
69
|
+
invalidTruncated,
|
|
70
|
+
invalidNote: `...and ${invalidTruncated} more invalid frontmatter file(s) omitted to conserve context.`,
|
|
71
|
+
}
|
|
72
|
+
: {}),
|
|
73
|
+
...(status.summary.invalid > 0
|
|
74
|
+
? {
|
|
75
|
+
repairHint: uncachedInvalid.length > 0
|
|
76
|
+
? `Run sync_pull to automatically repair cached invalid frontmatter files. For ${uncachedInvalid.length} uncached file(s) outside the sliding window, run sync_pull with id: "${exampleUncachedId}" (or "emit pull ${exampleUncachedId}" in CLI).`
|
|
77
|
+
: 'Run sync_pull (or "emit pull" in CLI) to automatically re-serialize and repair unquoted %-prefixed frontmatter files.',
|
|
78
|
+
}
|
|
79
|
+
: {}),
|
|
80
|
+
...(status.summary.conflicts > 0
|
|
81
|
+
? {
|
|
82
|
+
conflictsNote: `${status.summary.conflicts} preserved local copy(ies) exist in ${collection}/conflicts/ because a pull found content that diverged from the last synced baseline. Review each copy, merge valuable content manually, then delete it. Preserved copies are never pushed or pruned automatically, and sync_push refuses a posts/conflicts/ path with QUARANTINED_COPY_NOT_PUSHABLE.`,
|
|
83
|
+
}
|
|
84
|
+
: {}),
|
|
85
|
+
};
|
|
35
86
|
return {
|
|
36
87
|
content: [
|
|
37
88
|
{
|
|
38
89
|
type: 'text',
|
|
39
|
-
text: JSON.stringify(
|
|
90
|
+
text: JSON.stringify(responsePayload, null, 2),
|
|
40
91
|
},
|
|
41
92
|
],
|
|
42
93
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync-status.js","sourceRoot":"","sources":["../../../src/mcp/tools/sync-status.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,kBAAkB,
|
|
1
|
+
{"version":3,"file":"sync-status.js","sourceRoot":"","sources":["../../../src/mcp/tools/sync-status.ts"],"names":[],"mappings":"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"}
|
|
@@ -29,6 +29,10 @@ export interface PullBatchResult {
|
|
|
29
29
|
updated: number;
|
|
30
30
|
skipped: number;
|
|
31
31
|
deleted?: number;
|
|
32
|
+
/** Articles whose unpushed local edits were kept instead of applying remote changes. */
|
|
33
|
+
preserved?: number;
|
|
34
|
+
/** Total number of divergent local copies preserved under `<collection>/conflicts/`. */
|
|
35
|
+
quarantined?: number;
|
|
32
36
|
items: PullResult[];
|
|
33
37
|
}
|
|
34
38
|
/**
|
|
@@ -45,10 +49,12 @@ export interface PushAllResult {
|
|
|
45
49
|
total: number;
|
|
46
50
|
pushed: number;
|
|
47
51
|
skipped: number;
|
|
52
|
+
invalid: number;
|
|
48
53
|
results: PushResult[];
|
|
49
54
|
}
|
|
50
55
|
/**
|
|
51
56
|
* Orchestrates pushing all modified/untracked files in the workspace.
|
|
57
|
+
* Excludes synced and invalid (YAML parse error) files so invalid files do not crash batch push.
|
|
52
58
|
* Reusable across CLI and MCP servers.
|
|
53
59
|
*/
|
|
54
60
|
export declare function pushAll(options: PushAllOptions): Promise<PushAllResult>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../src/sync/orchestrator.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,aAAa,EAAa,MAAM,gBAAgB,CAAC;AAC/D,OAAO,
|
|
1
|
+
{"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../src/sync/orchestrator.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,aAAa,EAAa,MAAM,gBAAgB,CAAC;AAC/D,OAAO,EAKL,KAAK,UAAU,EACf,KAAK,yBAAyB,EAC/B,MAAM,WAAW,CAAC;AACnB,OAAO,EAAe,KAAK,UAAU,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AAI3E,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,sBAAuB,SAAQ,KAAK;IACxC,aAAa,EAAE,oBAAoB,EAAE,CAAC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IAEtB,YAAY,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,oBAAoB,EAAE,EAAE,KAAK,CAAC,EAAE,MAAM,EAKjF;CACF;AAED,MAAM,WAAW,gBAAiB,SAAQ,yBAAyB;IACjE,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,aAAa,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,UAAU,CAAA;KAAE,KAAK,IAAI,CAAC;CACvF;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wFAAwF;IACxF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wFAAwF;IACxF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,UAAU,EAAE,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CA4LnF;AAED,MAAM,WAAW,cAAe,SAAQ,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC;IAClE,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,aAAa,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,UAAU,EAAE,CAAC;CACvB;AAED;;;;GAIG;AACH,wBAAsB,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CA8B7E"}
|