emdash-emit 0.1.8 → 0.1.10

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 (148) hide show
  1. package/README.md +132 -28
  2. package/dist/bin/emit.d.ts.map +1 -1
  3. package/dist/bin/emit.js +6 -0
  4. package/dist/bin/emit.js.map +1 -1
  5. package/dist/cli/commands/conflicts.d.ts +4 -0
  6. package/dist/cli/commands/conflicts.d.ts.map +1 -0
  7. package/dist/cli/commands/conflicts.js +153 -0
  8. package/dist/cli/commands/conflicts.js.map +1 -0
  9. package/dist/cli/commands/delete.d.ts +4 -0
  10. package/dist/cli/commands/delete.d.ts.map +1 -0
  11. package/dist/cli/commands/delete.js +89 -0
  12. package/dist/cli/commands/delete.js.map +1 -0
  13. package/dist/cli/commands/doctor.d.ts +4 -0
  14. package/dist/cli/commands/doctor.d.ts.map +1 -0
  15. package/dist/cli/commands/doctor.js +82 -0
  16. package/dist/cli/commands/doctor.js.map +1 -0
  17. package/dist/cli/commands/new.d.ts.map +1 -1
  18. package/dist/cli/commands/new.js +52 -22
  19. package/dist/cli/commands/new.js.map +1 -1
  20. package/dist/cli/commands/profile.d.ts.map +1 -1
  21. package/dist/cli/commands/profile.js +67 -13
  22. package/dist/cli/commands/profile.js.map +1 -1
  23. package/dist/cli/commands/pull.d.ts +5 -0
  24. package/dist/cli/commands/pull.d.ts.map +1 -1
  25. package/dist/cli/commands/pull.js +119 -39
  26. package/dist/cli/commands/pull.js.map +1 -1
  27. package/dist/cli/commands/push.d.ts.map +1 -1
  28. package/dist/cli/commands/push.js +38 -1
  29. package/dist/cli/commands/push.js.map +1 -1
  30. package/dist/cli/commands/status.d.ts +19 -0
  31. package/dist/cli/commands/status.d.ts.map +1 -1
  32. package/dist/cli/commands/status.js +87 -5
  33. package/dist/cli/commands/status.js.map +1 -1
  34. package/dist/cli/context.d.ts +38 -1
  35. package/dist/cli/context.d.ts.map +1 -1
  36. package/dist/cli/context.js +129 -16
  37. package/dist/cli/context.js.map +1 -1
  38. package/dist/client/auth.d.ts +1 -0
  39. package/dist/client/auth.d.ts.map +1 -1
  40. package/dist/client/auth.js +1 -0
  41. package/dist/client/auth.js.map +1 -1
  42. package/dist/client/http.d.ts.map +1 -1
  43. package/dist/client/http.js +27 -10
  44. package/dist/client/http.js.map +1 -1
  45. package/dist/db/cache.d.ts +3 -0
  46. package/dist/db/cache.d.ts.map +1 -1
  47. package/dist/db/cache.js +39 -0
  48. package/dist/db/cache.js.map +1 -1
  49. package/dist/mcp/context.d.ts +8 -0
  50. package/dist/mcp/context.d.ts.map +1 -1
  51. package/dist/mcp/server.d.ts +8 -0
  52. package/dist/mcp/server.d.ts.map +1 -1
  53. package/dist/mcp/server.js +91 -15
  54. package/dist/mcp/server.js.map +1 -1
  55. package/dist/mcp/tool-errors.d.ts +16 -0
  56. package/dist/mcp/tool-errors.d.ts.map +1 -0
  57. package/dist/mcp/tool-errors.js +137 -0
  58. package/dist/mcp/tool-errors.js.map +1 -0
  59. package/dist/mcp/tools/profile.d.ts +9 -2
  60. package/dist/mcp/tools/profile.d.ts.map +1 -1
  61. package/dist/mcp/tools/profile.js +53 -36
  62. package/dist/mcp/tools/profile.js.map +1 -1
  63. package/dist/mcp/tools/sync-conflicts.d.ts +4 -0
  64. package/dist/mcp/tools/sync-conflicts.d.ts.map +1 -0
  65. package/dist/mcp/tools/sync-conflicts.js +100 -0
  66. package/dist/mcp/tools/sync-conflicts.js.map +1 -0
  67. package/dist/mcp/tools/sync-delete.d.ts +4 -0
  68. package/dist/mcp/tools/sync-delete.d.ts.map +1 -0
  69. package/dist/mcp/tools/sync-delete.js +77 -0
  70. package/dist/mcp/tools/sync-delete.js.map +1 -0
  71. package/dist/mcp/tools/sync-diff.d.ts.map +1 -1
  72. package/dist/mcp/tools/sync-diff.js +22 -8
  73. package/dist/mcp/tools/sync-diff.js.map +1 -1
  74. package/dist/mcp/tools/sync-doctor.d.ts +4 -0
  75. package/dist/mcp/tools/sync-doctor.d.ts.map +1 -0
  76. package/dist/mcp/tools/sync-doctor.js +57 -0
  77. package/dist/mcp/tools/sync-doctor.js.map +1 -0
  78. package/dist/mcp/tools/sync-new.d.ts.map +1 -1
  79. package/dist/mcp/tools/sync-new.js +49 -23
  80. package/dist/mcp/tools/sync-new.js.map +1 -1
  81. package/dist/mcp/tools/sync-pull.d.ts.map +1 -1
  82. package/dist/mcp/tools/sync-pull.js +132 -73
  83. package/dist/mcp/tools/sync-pull.js.map +1 -1
  84. package/dist/mcp/tools/sync-push.d.ts.map +1 -1
  85. package/dist/mcp/tools/sync-push.js +39 -33
  86. package/dist/mcp/tools/sync-push.js.map +1 -1
  87. package/dist/mcp/tools/sync-status.d.ts.map +1 -1
  88. package/dist/mcp/tools/sync-status.js +103 -11
  89. package/dist/mcp/tools/sync-status.js.map +1 -1
  90. package/dist/sync/conflicts.d.ts +89 -0
  91. package/dist/sync/conflicts.d.ts.map +1 -0
  92. package/dist/sync/conflicts.js +374 -0
  93. package/dist/sync/conflicts.js.map +1 -0
  94. package/dist/sync/delete.d.ts +58 -0
  95. package/dist/sync/delete.d.ts.map +1 -0
  96. package/dist/sync/delete.js +221 -0
  97. package/dist/sync/delete.js.map +1 -0
  98. package/dist/sync/diff.d.ts.map +1 -1
  99. package/dist/sync/diff.js +6 -3
  100. package/dist/sync/diff.js.map +1 -1
  101. package/dist/sync/doctor.d.ts +31 -0
  102. package/dist/sync/doctor.d.ts.map +1 -0
  103. package/dist/sync/doctor.js +224 -0
  104. package/dist/sync/doctor.js.map +1 -0
  105. package/dist/sync/media.d.ts +22 -0
  106. package/dist/sync/media.d.ts.map +1 -1
  107. package/dist/sync/media.js +342 -94
  108. package/dist/sync/media.js.map +1 -1
  109. package/dist/sync/new.d.ts +31 -0
  110. package/dist/sync/new.d.ts.map +1 -1
  111. package/dist/sync/new.js +139 -2
  112. package/dist/sync/new.js.map +1 -1
  113. package/dist/sync/orchestrator.d.ts +6 -0
  114. package/dist/sync/orchestrator.d.ts.map +1 -1
  115. package/dist/sync/orchestrator.js +54 -27
  116. package/dist/sync/orchestrator.js.map +1 -1
  117. package/dist/sync/preflight.d.ts.map +1 -1
  118. package/dist/sync/preflight.js +29 -3
  119. package/dist/sync/preflight.js.map +1 -1
  120. package/dist/sync/pull.d.ts +51 -0
  121. package/dist/sync/pull.d.ts.map +1 -1
  122. package/dist/sync/pull.js +289 -58
  123. package/dist/sync/pull.js.map +1 -1
  124. package/dist/sync/push.d.ts +12 -0
  125. package/dist/sync/push.d.ts.map +1 -1
  126. package/dist/sync/push.js +69 -24
  127. package/dist/sync/push.js.map +1 -1
  128. package/dist/sync/status.d.ts +21 -1
  129. package/dist/sync/status.d.ts.map +1 -1
  130. package/dist/sync/status.js +66 -6
  131. package/dist/sync/status.js.map +1 -1
  132. package/dist/sync/taxonomies.d.ts +14 -5
  133. package/dist/sync/taxonomies.d.ts.map +1 -1
  134. package/dist/sync/taxonomies.js +142 -9
  135. package/dist/sync/taxonomies.js.map +1 -1
  136. package/dist/utils/config.d.ts +23 -0
  137. package/dist/utils/config.d.ts.map +1 -1
  138. package/dist/utils/config.js +41 -4
  139. package/dist/utils/config.js.map +1 -1
  140. package/dist/utils/frontmatter.d.ts +51 -2
  141. package/dist/utils/frontmatter.d.ts.map +1 -1
  142. package/dist/utils/frontmatter.js +234 -9
  143. package/dist/utils/frontmatter.js.map +1 -1
  144. package/dist/utils/profile.d.ts +3 -3
  145. package/dist/utils/profile.d.ts.map +1 -1
  146. package/dist/utils/profile.js +105 -8
  147. package/dist/utils/profile.js.map +1 -1
  148. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-conflicts.js","sourceRoot":"","sources":["../../../src/mcp/tools/sync-conflicts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { ContextResolver } from '../context.js';
3
+ export declare function registerSyncDeleteTool(server: McpServer, resolveContext: ContextResolver): void;
4
+ //# sourceMappingURL=sync-delete.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-delete.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/sync-delete.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,eAAe,EAAiB,MAAM,eAAe,CAAC;AAIpE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,eAAe,GAAG,IAAI,CA6D/F"}
@@ -0,0 +1,77 @@
1
+ /*
2
+ * Copyright (C) 2026 SPORT-SERVICE RS★R
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in all
12
+ * copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+ import { z } from 'zod';
23
+ import { deleteArticle } from '../../sync/delete.js';
24
+ import { formatToolError, formatToolSuccess } from '../tool-errors.js';
25
+ export function registerSyncDeleteTool(server, resolveContext) {
26
+ server.tool('sync_delete', 'Safely delete an article from both the local workspace and remote EmDash server. Enforces strict safety guards: rejects deletion if unpushed local modifications exist, requires "allowDeletePublished: true" to delete published articles, saves an automatic rescue backup to posts/conflicts/<file>.deleted.md, and preserves referenced media files in media/.', {
27
+ filePath: z
28
+ .string()
29
+ .optional()
30
+ .describe('Workspace-relative file path to delete (e.g. posts/draft/20261108_01M6...-my-slug.md)'),
31
+ id: z.string().optional().describe('Article ULID to delete'),
32
+ allowDeletePublished: z
33
+ .boolean()
34
+ .optional()
35
+ .describe('Explicit confirmation required to delete a published live article'),
36
+ dryRun: z
37
+ .boolean()
38
+ .optional()
39
+ .describe('Preview deletion metadata, line count, and referenced media without deleting'),
40
+ collection: z
41
+ .string()
42
+ .optional()
43
+ .describe('Collection name containing the article (defaults to "posts")'),
44
+ profile: z.string().optional().describe('Target profile name for multi-site setups'),
45
+ }, async (args) => {
46
+ let ctx;
47
+ try {
48
+ ctx = resolveContext(args.profile);
49
+ }
50
+ catch (error) {
51
+ return formatToolError(error);
52
+ }
53
+ if (!args.filePath && !args.id) {
54
+ return formatToolError(new Error('Please specify either "filePath" or "id" of the article to delete.'));
55
+ }
56
+ try {
57
+ const collection = args.collection || ctx.config.defaultCollection;
58
+ const result = await deleteArticle({
59
+ workspaceRoot: ctx.root,
60
+ cache: ctx.cache,
61
+ filePath: args.filePath,
62
+ id: args.id,
63
+ collection,
64
+ allowDeletePublished: args.allowDeletePublished,
65
+ dryRun: args.dryRun,
66
+ origin: ctx.origin,
67
+ token: ctx.auth?.token,
68
+ refreshToken: ctx.auth?.refreshToken,
69
+ });
70
+ return formatToolSuccess(result, ctx.meta);
71
+ }
72
+ catch (error) {
73
+ return formatToolError(error, ctx.meta);
74
+ }
75
+ });
76
+ }
77
+ //# sourceMappingURL=sync-delete.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-delete.js","sourceRoot":"","sources":["../../../src/mcp/tools/sync-delete.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEvE,MAAM,UAAU,sBAAsB,CAAC,MAAiB,EAAE,cAA+B;IACvF,MAAM,CAAC,IAAI,CACT,aAAa,EACb,oWAAoW,EACpW;QACE,QAAQ,EAAE,CAAC;aACR,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,uFAAuF,CACxF;QACH,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC;QAC5D,oBAAoB,EAAE,CAAC;aACpB,OAAO,EAAE;aACT,QAAQ,EAAE;aACV,QAAQ,CAAC,mEAAmE,CAAC;QAChF,MAAM,EAAE,CAAC;aACN,OAAO,EAAE;aACT,QAAQ,EAAE;aACV,QAAQ,CAAC,8EAA8E,CAAC;QAC3F,UAAU,EAAE,CAAC;aACV,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,8DAA8D,CAAC;QAC3E,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;QAED,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;YAC/B,OAAO,eAAe,CACpB,IAAI,KAAK,CAAC,oEAAoE,CAAC,CAChF,CAAC;QACJ,CAAC;QAED,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,GAAG,CAAC,MAAM,CAAC,iBAAiB,CAAC;YACnE,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC;gBACjC,aAAa,EAAE,GAAG,CAAC,IAAI;gBACvB,KAAK,EAAE,GAAG,CAAC,KAAK;gBAChB,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,EAAE,EAAE,IAAI,CAAC,EAAE;gBACX,UAAU;gBACV,oBAAoB,EAAE,IAAI,CAAC,oBAAoB;gBAC/C,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,KAAK;gBACtB,YAAY,EAAE,GAAG,CAAC,IAAI,EAAE,YAAY;aACrC,CAAC,CAAC;YAEH,OAAO,iBAAiB,CAAC,MAA4C,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QACnF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,eAAe,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"sync-diff.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/sync-diff.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAGrD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,eAAe,GAAG,IAAI,CAiC7F"}
1
+ {"version":3,"file":"sync-diff.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/sync-diff.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,CA6C7F"}
@@ -21,6 +21,7 @@
21
21
  */
22
22
  import { z } from 'zod';
23
23
  import { inspectArticleDiff } from '../../sync/diff.js';
24
+ import { formatToolError } from '../tool-errors.js';
24
25
  export function registerSyncDiffTool(server, resolveContext) {
25
26
  server.tool('sync_diff', 'Display line-by-line differences between local article edits and the baseline snapshot/remote version before pushing. Useful for reviewing changes or diagnosing unpushed modifications.', {
26
27
  filePath: z
@@ -30,18 +31,31 @@ export function registerSyncDiffTool(server, resolveContext) {
30
31
  id: z.string().optional().describe('Article ID (ULID) to inspect'),
31
32
  profile: z.string().optional().describe('Target profile name for multi-site setups'),
32
33
  }, async (args) => {
33
- const ctx = resolveContext(args.profile);
34
- const inspection = inspectArticleDiff({
35
- workspaceRoot: ctx.root,
36
- cache: ctx.cache,
37
- filePath: args.filePath,
38
- id: args.id,
39
- });
34
+ let ctx;
35
+ try {
36
+ ctx = resolveContext(args.profile);
37
+ }
38
+ catch (error) {
39
+ return formatToolError(error);
40
+ }
41
+ let inspection;
42
+ try {
43
+ inspection = inspectArticleDiff({
44
+ workspaceRoot: ctx.root,
45
+ cache: ctx.cache,
46
+ filePath: args.filePath,
47
+ id: args.id,
48
+ });
49
+ }
50
+ catch (error) {
51
+ return formatToolError(error, ctx.meta);
52
+ }
53
+ const metaSuffix = `\n\n_meta: ${JSON.stringify(ctx.meta)}`;
40
54
  return {
41
55
  content: [
42
56
  {
43
57
  type: 'text',
44
- text: inspection.formattedOutput,
58
+ text: `${inspection.formattedOutput}${metaSuffix}`,
45
59
  },
46
60
  ],
47
61
  };
@@ -1 +1 @@
1
- {"version":3,"file":"sync-diff.js","sourceRoot":"","sources":["../../../src/mcp/tools/sync-diff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAExD,MAAM,UAAU,oBAAoB,CAAC,MAAiB,EAAE,cAA+B;IACrF,MAAM,CAAC,IAAI,CACT,WAAW,EACX,0LAA0L,EAC1L;QACE,QAAQ,EAAE,CAAC;aACR,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,iGAAiG,CAClG;QACH,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,8BAA8B,CAAC;QAClE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,2CAA2C,CAAC;KACrF,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,MAAM,GAAG,GAAG,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACzC,MAAM,UAAU,GAAG,kBAAkB,CAAC;YACpC,aAAa,EAAE,GAAG,CAAC,IAAI;YACvB,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,EAAE,EAAE,IAAI,CAAC,EAAE;SACZ,CAAC,CAAC;QAEH,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,UAAU,CAAC,eAAe;iBACjC;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"sync-diff.js","sourceRoot":"","sources":["../../../src/mcp/tools/sync-diff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,kBAAkB,EAA8B,MAAM,oBAAoB,CAAC;AACpF,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,UAAU,oBAAoB,CAAC,MAAiB,EAAE,cAA+B;IACrF,MAAM,CAAC,IAAI,CACT,WAAW,EACX,0LAA0L,EAC1L;QACE,QAAQ,EAAE,CAAC;aACR,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,iGAAiG,CAClG;QACH,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,8BAA8B,CAAC;QAClE,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,IAAI,UAAiC,CAAC;QACtC,IAAI,CAAC;YACH,UAAU,GAAG,kBAAkB,CAAC;gBAC9B,aAAa,EAAE,GAAG,CAAC,IAAI;gBACvB,KAAK,EAAE,GAAG,CAAC,KAAK;gBAChB,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,EAAE,EAAE,IAAI,CAAC,EAAE;aACZ,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,eAAe,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QAC1C,CAAC;QAED,MAAM,UAAU,GAAG,cAAc,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QAE5D,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,GAAG,UAAU,CAAC,eAAe,GAAG,UAAU,EAAE;iBACnD;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { ContextResolver } from '../context.js';
3
+ export declare function registerSyncDoctorTool(server: McpServer, resolveContext: ContextResolver): void;
4
+ //# sourceMappingURL=sync-doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-doctor.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/sync-doctor.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,eAAe,EAAiB,MAAM,eAAe,CAAC;AAIpE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,eAAe,GAAG,IAAI,CAoC/F"}
@@ -0,0 +1,57 @@
1
+ /*
2
+ * Copyright (C) 2026 SPORT-SERVICE RS★R
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in all
12
+ * copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+ import { z } from 'zod';
23
+ import { runWorkspaceDoctor } from '../../sync/doctor.js';
24
+ import { formatToolError, formatToolSuccess } from '../tool-errors.js';
25
+ export function registerSyncDoctorTool(server, resolveContext) {
26
+ server.tool('sync_doctor', 'Run comprehensive workspace diagnostics: verifies version compatibility, profile/config origin consistency, frontmatter syntax integrity across all articles, quarantined conflict copies, unpushed modifications, and referenced media existence.', {
27
+ collection: z
28
+ .string()
29
+ .optional()
30
+ .describe('Collection to diagnose (defaults to defaultCollection or "posts")'),
31
+ profile: z.string().optional().describe('Target profile name for multi-site setups'),
32
+ }, async (args) => {
33
+ let ctx;
34
+ try {
35
+ ctx = resolveContext(args.profile);
36
+ }
37
+ catch (error) {
38
+ return formatToolError(error);
39
+ }
40
+ try {
41
+ const collection = args.collection || ctx.config.defaultCollection || 'posts';
42
+ const report = await runWorkspaceDoctor({
43
+ workspaceRoot: ctx.root,
44
+ cache: ctx.cache,
45
+ config: ctx.config,
46
+ profileName: ctx.auth.profileName,
47
+ profileOrigin: ctx.auth.origin,
48
+ collection,
49
+ });
50
+ return formatToolSuccess(report, ctx.meta);
51
+ }
52
+ catch (err) {
53
+ return formatToolError(err, ctx.meta);
54
+ }
55
+ });
56
+ }
57
+ //# sourceMappingURL=sync-doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-doctor.js","sourceRoot":"","sources":["../../../src/mcp/tools/sync-doctor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEvE,MAAM,UAAU,sBAAsB,CAAC,MAAiB,EAAE,cAA+B;IACvF,MAAM,CAAC,IAAI,CACT,aAAa,EACb,oPAAoP,EACpP;QACE,UAAU,EAAE,CAAC;aACV,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,mEAAmE,CAAC;QAChF,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;QAED,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,GAAG,CAAC,MAAM,CAAC,iBAAiB,IAAI,OAAO,CAAC;YAC9E,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC;gBACtC,aAAa,EAAE,GAAG,CAAC,IAAI;gBACvB,KAAK,EAAE,GAAG,CAAC,KAAK;gBAChB,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,WAAW,EAAE,GAAG,CAAC,IAAI,CAAC,WAAW;gBACjC,aAAa,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM;gBAC9B,UAAU;aACX,CAAC,CAAC;YAEH,OAAO,iBAAiB,CAAC,MAA4C,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QACnF,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,eAAe,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QACxC,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"sync-new.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/sync-new.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAIrD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,eAAe,GAAG,IAAI,CA6C5F"}
1
+ {"version":3,"file":"sync-new.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/sync-new.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,eAAe,EAAiB,MAAM,eAAe,CAAC;AASpE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,eAAe,GAAG,IAAI,CAwE5F"}
@@ -20,8 +20,9 @@
20
20
  * SOFTWARE.
21
21
  */
22
22
  import { z } from 'zod';
23
- import { createArticleScaffold } from '../../sync/new.js';
23
+ import { createArticleScaffold, checkRemoteDuplicateSlug, DuplicateSlugError, } from '../../sync/new.js';
24
24
  import { getLocalTaxonomiesSummary, formatTaxonomiesHint } from '../../sync/taxonomies.js';
25
+ import { formatToolError } from '../tool-errors.js';
25
26
  export function registerSyncNewTool(server, resolveContext) {
26
27
  server.tool('sync_new', 'Create a new article draft scaffold in posts/draft/ with standardized frontmatter (ULID, slug, title, default bylines). Returns the created relative file path and available categories/tags hints (sorted by usage) so you can edit the Markdown file directly before pushing.', {
27
28
  slug: z.string().describe('URL slug for the new article'),
@@ -37,28 +38,53 @@ export function registerSyncNewTool(server, resolveContext) {
37
38
  .describe('Author byline slug (defaults to first cached non-guest author by slug)'),
38
39
  profile: z.string().optional().describe('Target profile name for multi-site setups'),
39
40
  }, async (args) => {
40
- const ctx = resolveContext(args.profile);
41
- const collection = args.collection || ctx.config.defaultCollection;
42
- const res = createArticleScaffold({
43
- slug: args.slug,
44
- workspaceRoot: ctx.root,
45
- collection,
46
- title: args.title,
47
- locale: args.locale || ctx.config.defaultLocale,
48
- byline: args.byline,
49
- cache: ctx.cache,
50
- });
51
- const taxSummary = getLocalTaxonomiesSummary(ctx.root);
52
- const taxHint = formatTaxonomiesHint(taxSummary, { maxTags: 60 });
53
- const hintBlock = taxHint ? `\n\n${taxHint}` : '';
54
- return {
55
- content: [
56
- {
57
- type: 'text',
58
- text: `✅ Created new draft article '${args.slug}' (ID: ${res.id}) at ${res.filePath}.${hintBlock}\n\nYou can now edit the file directly and sync it with sync_push.`,
59
- },
60
- ],
61
- };
41
+ let ctx;
42
+ try {
43
+ ctx = resolveContext(args.profile);
44
+ }
45
+ catch (error) {
46
+ return formatToolError(error);
47
+ }
48
+ try {
49
+ const collection = args.collection || ctx.config.defaultCollection;
50
+ // Best-effort remote duplicate check if connected
51
+ if (ctx.origin && ctx.auth?.token) {
52
+ const remoteDup = await checkRemoteDuplicateSlug({
53
+ origin: ctx.origin,
54
+ token: ctx.auth.token,
55
+ collection,
56
+ slug: args.slug,
57
+ }).catch(() => null);
58
+ if (remoteDup) {
59
+ throw new DuplicateSlugError(remoteDup);
60
+ }
61
+ }
62
+ const res = createArticleScaffold({
63
+ slug: args.slug,
64
+ workspaceRoot: ctx.root,
65
+ collection,
66
+ title: args.title,
67
+ locale: args.locale || ctx.config.defaultLocale,
68
+ byline: args.byline,
69
+ cache: ctx.cache,
70
+ });
71
+ const taxSummary = getLocalTaxonomiesSummary(ctx.root);
72
+ const taxHint = formatTaxonomiesHint(taxSummary, { maxTags: 60 });
73
+ const hintBlock = taxHint ? `\n\n${taxHint}` : '';
74
+ const metaSuffix = `\n\n_meta: ${JSON.stringify(ctx.meta)}`;
75
+ return {
76
+ content: [
77
+ {
78
+ type: 'text',
79
+ text: `✅ Created new draft article '${args.slug}' (ID: ${res.id}) at ${res.filePath}.${hintBlock}\n\nYou can now edit the file directly and sync it with sync_push.${metaSuffix}`,
80
+ },
81
+ ],
82
+ };
83
+ }
84
+ catch (error) {
85
+ // Slug validation, byline resolution, and taxonomy hint reads all fail here.
86
+ return formatToolError(error, ctx?.meta);
87
+ }
62
88
  });
63
89
  }
64
90
  //# sourceMappingURL=sync-new.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sync-new.js","sourceRoot":"","sources":["../../../src/mcp/tools/sync-new.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAE,yBAAyB,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAE3F,MAAM,UAAU,mBAAmB,CAAC,MAAiB,EAAE,cAA+B;IACpF,MAAM,CAAC,IAAI,CACT,UAAU,EACV,iRAAiR,EACjR;QACE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8BAA8B,CAAC;QACzD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC;QACtD,UAAU,EAAE,CAAC;aACV,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,mDAAmD,CAAC;QAChE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC;QAC3E,MAAM,EAAE,CAAC;aACN,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,wEAAwE,CAAC;QACrF,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,2CAA2C,CAAC;KACrF,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,MAAM,GAAG,GAAG,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACzC,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,GAAG,CAAC,MAAM,CAAC,iBAAiB,CAAC;QACnE,MAAM,GAAG,GAAG,qBAAqB,CAAC;YAChC,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,aAAa,EAAE,GAAG,CAAC,IAAI;YACvB,UAAU;YACV,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,aAAa;YAC/C,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,KAAK,EAAE,GAAG,CAAC,KAAK;SACjB,CAAC,CAAC;QAEH,MAAM,UAAU,GAAG,yBAAyB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACvD,MAAM,OAAO,GAAG,oBAAoB,CAAC,UAAU,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;QAClE,MAAM,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,OAAO,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAElD,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,gCAAgC,IAAI,CAAC,IAAI,UAAU,GAAG,CAAC,EAAE,QAAQ,GAAG,CAAC,QAAQ,IAAI,SAAS,oEAAoE;iBACrK;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"sync-new.js","sourceRoot":"","sources":["../../../src/mcp/tools/sync-new.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"sync-pull.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/sync-pull.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAYrD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,eAAe,GAAG,IAAI,CA+P9F"}
1
+ {"version":3,"file":"sync-pull.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/sync-pull.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,eAAe,EAAiB,MAAM,eAAe,CAAC;AAapE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,eAAe,GAAG,IAAI,CA6T9F"}
@@ -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, SyncPruneConflictError } from '../../sync/orchestrator.js';
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
- const ctx = resolveContext(args.profile);
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,41 @@ export function registerSyncPullTools(server, resolveContext) {
74
81
  id: args.id,
75
82
  });
76
83
  if (targetId) {
77
- const res = await pullArticle(collection, targetId, {
78
- workspaceRoot: ctx.root,
79
- cache: ctx.cache,
80
- origin,
81
- token: ctx.auth.token,
82
- refreshToken: ctx.auth.refreshToken,
83
- force: args.force,
84
- });
85
- const actionText = res.skipped
86
- ? 'ℹ️ Article is already up-to-date'
87
- : '✅ Successfully pulled article';
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.healed
99
+ ? '🛠️ Repaired frontmatter syntax (unpushed local body was strictly preserved)'
100
+ : res.localEditsPreserved
101
+ ? 'ℹ️ Local edits preserved (remote changes were NOT applied)'
102
+ : res.skipped
103
+ ? 'ℹ️ Article is already up-to-date'
104
+ : '✅ Successfully pulled article';
88
105
  const titleText = res.title ? ` "${res.title}"` : '';
106
+ const warnLine = ctx.originWarning ? `\n\n${ctx.originWarning}` : '';
107
+ const quarantineNotice = formatQuarantineNotice(res.quarantined);
108
+ const quarantineLine = quarantineNotice ? `\n\n${quarantineNotice}` : '';
109
+ const nextStep = res.localEditsPreserved
110
+ ? '\n\nYour local version is intact. Push it with sync_push to publish your edits, ' +
111
+ 'or re-run sync_pull with force: true to accept the remote version instead.'
112
+ : '\n\nYou can now read or edit this local Markdown file directly.';
113
+ const metaSuffix = `\n\n_meta: ${JSON.stringify(ctx.meta)}`;
89
114
  return {
90
115
  content: [
91
116
  {
92
117
  type: 'text',
93
- text: `${actionText}${titleText} (${res.slug})\nFile path: ${res.filePath}\nStatus: ${res.status}\n\nYou can now read or edit this local Markdown file directly.`,
118
+ text: `${actionText}${titleText} (${res.slug})\nFile path: ${res.filePath}\nStatus: ${res.status}${quarantineLine}${warnLine}${nextStep}${metaSuffix}`,
94
119
  },
95
120
  ],
96
121
  };
@@ -148,6 +173,13 @@ export function registerSyncPullTools(server, resolveContext) {
148
173
  const listLines = sampleItems.map((item) => ` - [${item.status}] ${item.filePath}${item.title ? ` (${item.title})` : ''}`);
149
174
  const headerLabel = updatedItems.length > 0 ? 'Updated Articles' : 'Recent Articles in Workspace';
150
175
  const detailBlock = listLines.length > 0 ? `\n\n${headerLabel}:\n${listLines.join('\n')}` : '';
176
+ const preservedMsg = batchResult.preserved && batchResult.preserved > 0
177
+ ? `\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.`
178
+ : '';
179
+ const quarantineNotices = sortedItems
180
+ .map((item) => formatQuarantineNotice(item.quarantined))
181
+ .filter((notice) => notice.length > 0);
182
+ const quarantineMsg = quarantineNotices.length > 0 ? `\n\n${quarantineNotices.join('\n\n')}` : '';
151
183
  // 3. Pull media if includeMedia
152
184
  let mediaMsg = '';
153
185
  if (includeMedia) {
@@ -162,63 +194,68 @@ export function registerSyncPullTools(server, resolveContext) {
162
194
  });
163
195
  mediaMsg = `\nMedia: ${mediaResult.total} items (${mediaResult.downloaded} downloaded, ${mediaResult.skipped} up-to-date).`;
164
196
  }
197
+ const warnLine = ctx.originWarning ? `\n\n${ctx.originWarning}` : '';
198
+ const metaSuffix = `\n\n_meta: ${JSON.stringify(ctx.meta)}`;
165
199
  return {
166
200
  content: [
167
201
  {
168
202
  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.`,
203
+ text: `✅ Synced ${batchResult.total} articles (${batchResult.updated} updated, ${batchResult.skipped} up-to-date/skipped${deletedMsg}).${taxonomiesMsg}${mediaMsg}${preservedMsg}${quarantineMsg}${detailBlock}${warnLine}${metaSuffix}\n\nYou can now read or edit these local Markdown files directly.`,
170
204
  },
171
205
  ],
172
206
  };
173
207
  }
174
208
  catch (error) {
175
- if (error instanceof SyncPruneConflictError) {
176
- return {
177
- isError: true,
178
- content: [
179
- {
180
- type: 'text',
181
- text: `❌ ${error.message}`,
182
- },
183
- ],
184
- };
185
- }
186
- throw error;
209
+ return formatToolError(error, ctx?.meta);
187
210
  }
188
211
  });
189
212
  // sync_pull_taxonomies
190
213
  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
214
  profile: z.string().optional().describe('Target profile name for multi-site setups'),
192
215
  }, async (args) => {
193
- const ctx = resolveContext(args.profile);
194
- const res = await pullTaxonomies({
195
- workspaceRoot: ctx.root,
196
- origin: ctx.origin,
197
- token: ctx.auth.token,
198
- refreshToken: ctx.auth.refreshToken,
199
- });
200
- const taxSummary = getLocalTaxonomiesSummary(ctx.root);
201
- const taxHint = formatTaxonomiesHint(taxSummary, { maxTags: 200 });
202
- const hintBlock = taxHint ? `\n\n${taxHint}` : '';
203
- const failNotes = [];
204
- if (res.categoriesFailed)
205
- failNotes.push('categories');
206
- if (res.tagsFailed)
207
- failNotes.push('tags');
208
- const statusLine = failNotes.length > 0
209
- ? `⚠️ Warning: Failed to fetch remote ${failNotes.join(' and ')} (preserved existing local definitions in categories/ and tags/).`
210
- : `✅ Successfully pulled taxonomies (${res.categoriesCount} categories, ${res.tagsCount} tags) into categories/ and tags/.`;
211
- return {
212
- content: [
213
- {
214
- type: 'text',
215
- text: `${statusLine}${hintBlock}`,
216
- },
217
- ],
218
- };
216
+ try {
217
+ const ctx = resolveContext(args.profile);
218
+ const res = await pullTaxonomies({
219
+ workspaceRoot: ctx.root,
220
+ origin: ctx.origin,
221
+ token: ctx.auth.token,
222
+ refreshToken: ctx.auth.refreshToken,
223
+ });
224
+ const taxSummary = getLocalTaxonomiesSummary(ctx.root);
225
+ const taxHint = formatTaxonomiesHint(taxSummary, { maxTags: 200 });
226
+ const hintBlock = taxHint ? `\n\n${taxHint}` : '';
227
+ const failNotes = [];
228
+ if (res.categoriesFailed)
229
+ failNotes.push('categories');
230
+ if (res.tagsFailed)
231
+ failNotes.push('tags');
232
+ const statusLine = failNotes.length > 0
233
+ ? `⚠️ Warning: Failed to fetch remote ${failNotes.join(' and ')} (preserved existing local definitions in categories/ and tags/).`
234
+ : `✅ Successfully pulled taxonomies (${res.categoriesCount} categories, ${res.tagsCount} tags) into categories/ and tags/.`;
235
+ const metaSuffix = `\n\n_meta: ${JSON.stringify(ctx.meta)}`;
236
+ return {
237
+ content: [
238
+ {
239
+ type: 'text',
240
+ text: `${statusLine}${hintBlock}${metaSuffix}`,
241
+ },
242
+ ],
243
+ };
244
+ }
245
+ catch (error) {
246
+ return formatToolError(error);
247
+ }
219
248
  });
220
249
  // sync_pull_media
221
- 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.', {
250
+ 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). Can pull all media, a limited batch, or targeted media referenced by a specific article.', {
251
+ article: z
252
+ .string()
253
+ .optional()
254
+ .describe('Target article ULID or Markdown file path to pull only media referenced by that article'),
255
+ collection: z
256
+ .string()
257
+ .optional()
258
+ .describe('Collection name when using article (defaults to "posts")'),
222
259
  limit: z
223
260
  .number()
224
261
  .optional()
@@ -227,24 +264,46 @@ export function registerSyncPullTools(server, resolveContext) {
227
264
  downloadFiles: z.boolean().optional().describe('Download binary files (defaults to true)'),
228
265
  profile: z.string().optional().describe('Target profile name for multi-site setups'),
229
266
  }, async (args) => {
230
- const ctx = resolveContext(args.profile);
231
- const res = await pullMedia({
232
- workspaceRoot: ctx.root,
233
- origin: ctx.origin,
234
- token: ctx.auth.token,
235
- refreshToken: ctx.auth.refreshToken,
236
- limit: args.limit || ctx.config.mediaSyncLimit || 300,
237
- all: args.all,
238
- downloadFiles: args.downloadFiles,
239
- });
240
- return {
241
- content: [
242
- {
243
- type: 'text',
244
- text: `✅ Successfully pulled media: ${res.total} items (${res.downloaded} downloaded, ${res.skipped} skipped/up-to-date).`,
245
- },
246
- ],
247
- };
267
+ try {
268
+ const ctx = resolveContext(args.profile);
269
+ const res = await pullMedia({
270
+ workspaceRoot: ctx.root,
271
+ origin: ctx.origin,
272
+ token: ctx.auth.token,
273
+ refreshToken: ctx.auth.refreshToken,
274
+ article: args.article,
275
+ collection: args.collection || ctx.config.defaultCollection,
276
+ limit: args.limit || ctx.config.mediaSyncLimit || 300,
277
+ all: args.all,
278
+ downloadFiles: args.downloadFiles,
279
+ });
280
+ const metaSuffix = `\n\n_meta: ${JSON.stringify(ctx.meta)}`;
281
+ if (args.article) {
282
+ const failedMsg = res.failed ? `, ${res.failed} failed` : '';
283
+ const idsList = res.mediaIds && res.mediaIds.length > 0
284
+ ? `\nMedia IDs: ${res.mediaIds.join(', ')}`
285
+ : '';
286
+ return {
287
+ content: [
288
+ {
289
+ type: 'text',
290
+ text: `✅ Successfully pulled media for article '${res.articleId || args.article}': ${res.total} referenced item(s) (${res.downloaded} downloaded, ${res.skipped} skipped/up-to-date${failedMsg}).${idsList}${metaSuffix}`,
291
+ },
292
+ ],
293
+ };
294
+ }
295
+ return {
296
+ content: [
297
+ {
298
+ type: 'text',
299
+ text: `✅ Successfully pulled media: ${res.total} items (${res.downloaded} downloaded, ${res.skipped} skipped/up-to-date).${metaSuffix}`,
300
+ },
301
+ ],
302
+ };
303
+ }
304
+ catch (error) {
305
+ return formatToolError(error);
306
+ }
248
307
  });
249
308
  }
250
309
  //# sourceMappingURL=sync-pull.js.map