emdash-emit 0.1.7 → 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 +237 -82
- package/dist/cli/commands/new.d.ts.map +1 -1
- package/dist/cli/commands/new.js +3 -1
- package/dist/cli/commands/new.js.map +1 -1
- 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 +17 -2
- 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 +93 -4
- 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/client/mapper.d.ts +12 -0
- package/dist/client/mapper.d.ts.map +1 -1
- package/dist/client/mapper.js +65 -0
- package/dist/client/mapper.js.map +1 -1
- package/dist/client/media.d.ts +141 -0
- package/dist/client/media.d.ts.map +1 -0
- package/dist/client/media.js +582 -0
- package/dist/client/media.js.map +1 -0
- package/dist/client/portable-text.d.ts +22 -1
- package/dist/client/portable-text.d.ts.map +1 -1
- package/dist/client/portable-text.js +85 -5
- package/dist/client/portable-text.js.map +1 -1
- package/dist/db/cache.d.ts +16 -0
- package/dist/db/cache.d.ts.map +1 -1
- package/dist/db/cache.js +67 -0
- package/dist/db/cache.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.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 +60 -15
- 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 +18 -70
- 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 +40 -21
- 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 +110 -86
- 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/diff.d.ts +36 -0
- package/dist/sync/diff.d.ts.map +1 -1
- package/dist/sync/diff.js +118 -0
- package/dist/sync/diff.js.map +1 -1
- package/dist/sync/media.d.ts +16 -0
- package/dist/sync/media.d.ts.map +1 -1
- package/dist/sync/media.js +180 -26
- package/dist/sync/media.js.map +1 -1
- package/dist/sync/merge.d.ts.map +1 -1
- package/dist/sync/merge.js +1 -0
- package/dist/sync/merge.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/preflight.d.ts +30 -2
- package/dist/sync/preflight.d.ts.map +1 -1
- package/dist/sync/preflight.js +274 -10
- package/dist/sync/preflight.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 +332 -6
- 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 +16 -1
- package/dist/utils/frontmatter.d.ts.map +1 -1
- package/dist/utils/frontmatter.js +66 -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 +4 -1
|
@@ -0,0 +1,62 @@
|
|
|
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 { ApiError } from '../client/error.js';
|
|
23
|
+
import { SyncPruneConflictError } from '../sync/orchestrator.js';
|
|
24
|
+
import { PushValidationError } from '../sync/push.js';
|
|
25
|
+
import { AmbiguousProfileError } from '../utils/profile.js';
|
|
26
|
+
function toolError(text) {
|
|
27
|
+
return {
|
|
28
|
+
isError: true,
|
|
29
|
+
content: [
|
|
30
|
+
{
|
|
31
|
+
type: 'text',
|
|
32
|
+
text,
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Formats a known Emit error into a structured MCP tool result.
|
|
39
|
+
*
|
|
40
|
+
* Without this, the MCP SDK converts a thrown error into `createToolError(String(error))`,
|
|
41
|
+
* which keeps only `error.message` and silently drops the structured diagnostics
|
|
42
|
+
* (`[CODE]`, HTTP status, endpoint, suggestion) that CLI users receive through
|
|
43
|
+
* `ApiError.toActionableString()`. AI agents need the same actionable detail.
|
|
44
|
+
*/
|
|
45
|
+
export function formatToolError(error) {
|
|
46
|
+
if (error instanceof ApiError) {
|
|
47
|
+
return toolError(error.toActionableString());
|
|
48
|
+
}
|
|
49
|
+
if (error instanceof PushValidationError) {
|
|
50
|
+
return toolError(JSON.stringify({
|
|
51
|
+
error: 'PREFLIGHT_VALIDATION_FAILED',
|
|
52
|
+
message: error.message,
|
|
53
|
+
errors: error.errors,
|
|
54
|
+
}, null, 2));
|
|
55
|
+
}
|
|
56
|
+
if (error instanceof SyncPruneConflictError || error instanceof AmbiguousProfileError) {
|
|
57
|
+
return toolError(`❌ ${error.message}`);
|
|
58
|
+
}
|
|
59
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
60
|
+
return toolError(`❌ ${message}`);
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=tool-errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-errors.js","sourceRoot":"","sources":["../../src/mcp/tool-errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAE5D,SAAS,SAAS,CAAC,IAAY;IAC7B,OAAO;QACL,OAAO,EAAE,IAAI;QACb,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAM;gBACZ,IAAI;aACL;SACF;KACF,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,IAAI,KAAK,YAAY,QAAQ,EAAE,CAAC;QAC9B,OAAO,SAAS,CAAC,KAAK,CAAC,kBAAkB,EAAE,CAAC,CAAC;IAC/C,CAAC;IAED,IAAI,KAAK,YAAY,mBAAmB,EAAE,CAAC;QACzC,OAAO,SAAS,CACd,IAAI,CAAC,SAAS,CACZ;YACE,KAAK,EAAE,6BAA6B;YACpC,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,MAAM,EAAE,KAAK,CAAC,MAAM;SACrB,EACD,IAAI,EACJ,CAAC,CACF,CACF,CAAC;IACJ,CAAC;IAED,IAAI,KAAK,YAAY,sBAAsB,IAAI,KAAK,YAAY,qBAAqB,EAAE,CAAC;QACtF,OAAO,SAAS,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,OAAO,SAAS,CAAC,KAAK,OAAO,EAAE,CAAC,CAAC;AACnC,CAAC"}
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
-
export
|
|
2
|
+
export interface ProfileToolOptions {
|
|
3
3
|
getActiveOverride: () => string | undefined;
|
|
4
4
|
setActiveOverride: (name: string | undefined) => void;
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Custom profiles.yaml path forwarded from createMcpServer. When set, profile tools read and
|
|
7
|
+
* write exactly the same file the sync tools resolve against, so an embedded server never
|
|
8
|
+
* reports profiles it cannot actually use.
|
|
9
|
+
*/
|
|
10
|
+
profilesPath?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function registerProfileTools(server: McpServer, options: ProfileToolOptions): void;
|
|
6
13
|
//# sourceMappingURL=profile.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"profile.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/profile.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"profile.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/profile.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIzE,MAAM,WAAW,kBAAkB;IACjC,iBAAiB,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;IAC5C,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IACtD;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAoFzF"}
|
|
@@ -21,28 +21,34 @@
|
|
|
21
21
|
*/
|
|
22
22
|
import { z } from 'zod';
|
|
23
23
|
import { loadProfilesFile, setActiveProfile } from '../../utils/profile.js';
|
|
24
|
+
import { formatToolError } from '../tool-errors.js';
|
|
24
25
|
export function registerProfileTools(server, options) {
|
|
25
26
|
// profile_list: List available profiles and indicate active one
|
|
26
|
-
server.tool('profile_list', 'List configured site profiles from ~/.config/emit/profiles.yaml, showing their origin URLs, workspace roots, and active selection.', {}, async () => {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
name,
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
27
|
+
server.tool('profile_list', 'List configured site profiles from the Emit profiles file (~/.config/emit/profiles.yaml by default), showing their origin URLs, workspace roots, and active selection.', {}, async () => {
|
|
28
|
+
try {
|
|
29
|
+
const data = loadProfilesFile(options.profilesPath);
|
|
30
|
+
const currentActive = options.getActiveOverride() || data.active;
|
|
31
|
+
const profiles = Object.entries(data.profiles).map(([name, p]) => ({
|
|
32
|
+
name,
|
|
33
|
+
origin: p.origin,
|
|
34
|
+
workspace: p.workspace,
|
|
35
|
+
active: name === currentActive,
|
|
36
|
+
}));
|
|
37
|
+
return {
|
|
38
|
+
content: [
|
|
39
|
+
{
|
|
40
|
+
type: 'text',
|
|
41
|
+
text: JSON.stringify({
|
|
42
|
+
activeProfile: currentActive,
|
|
43
|
+
profiles,
|
|
44
|
+
}, null, 2),
|
|
45
|
+
},
|
|
46
|
+
],
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
return formatToolError(error);
|
|
51
|
+
}
|
|
46
52
|
});
|
|
47
53
|
// profile_switch: Switch active profile for this session or globally
|
|
48
54
|
server.tool('profile_switch', 'Switch the active site profile for the current MCP session (or globally with persist: true) when managing multiple EmDash instances.', {
|
|
@@ -50,32 +56,39 @@ export function registerProfileTools(server, options) {
|
|
|
50
56
|
persist: z
|
|
51
57
|
.boolean()
|
|
52
58
|
.optional()
|
|
53
|
-
.describe('If true, updates active profile in
|
|
59
|
+
.describe('If true, updates active profile in profiles.yaml permanently'),
|
|
54
60
|
}, async (args) => {
|
|
55
|
-
|
|
56
|
-
|
|
61
|
+
try {
|
|
62
|
+
const data = loadProfilesFile(options.profilesPath);
|
|
63
|
+
if (!data.profiles[args.name]) {
|
|
64
|
+
// Marked as a tool error so clients/agents can branch on isError instead of scraping text.
|
|
65
|
+
return {
|
|
66
|
+
isError: true,
|
|
67
|
+
content: [
|
|
68
|
+
{
|
|
69
|
+
type: 'text',
|
|
70
|
+
text: `❌ Profile "${args.name}" not found. Available profiles: ${Object.keys(data.profiles).join(', ') || 'none'}.`,
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
if (args.persist) {
|
|
76
|
+
setActiveProfile(args.name, options.profilesPath);
|
|
77
|
+
}
|
|
78
|
+
options.setActiveOverride(args.name);
|
|
79
|
+
const p = data.profiles[args.name];
|
|
57
80
|
return {
|
|
58
81
|
content: [
|
|
59
82
|
{
|
|
60
83
|
type: 'text',
|
|
61
|
-
text:
|
|
84
|
+
text: `✅ Switched active profile to "${args.name}" (origin: ${p.origin}, workspace: ${p.workspace}${args.persist ? ', persisted to profiles.yaml' : ''}).`,
|
|
62
85
|
},
|
|
63
86
|
],
|
|
64
87
|
};
|
|
65
88
|
}
|
|
66
|
-
|
|
67
|
-
|
|
89
|
+
catch (error) {
|
|
90
|
+
return formatToolError(error);
|
|
68
91
|
}
|
|
69
|
-
options.setActiveOverride(args.name);
|
|
70
|
-
const p = data.profiles[args.name];
|
|
71
|
-
return {
|
|
72
|
-
content: [
|
|
73
|
-
{
|
|
74
|
-
type: 'text',
|
|
75
|
-
text: `✅ Switched active profile to "${args.name}" (origin: ${p.origin}, workspace: ${p.workspace}${args.persist ? ', persisted to profiles.yaml' : ''}).`,
|
|
76
|
-
},
|
|
77
|
-
],
|
|
78
|
-
};
|
|
79
92
|
});
|
|
80
93
|
}
|
|
81
94
|
//# sourceMappingURL=profile.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"profile.js","sourceRoot":"","sources":["../../../src/mcp/tools/profile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"profile.js","sourceRoot":"","sources":["../../../src/mcp/tools/profile.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync-diff.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/sync-diff.ts"],"names":[],"mappings":"
|
|
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,CA2C7F"}
|
|
@@ -20,11 +20,8 @@
|
|
|
20
20
|
* SOFTWARE.
|
|
21
21
|
*/
|
|
22
22
|
import { z } from 'zod';
|
|
23
|
-
import
|
|
24
|
-
import
|
|
25
|
-
import crypto from 'node:crypto';
|
|
26
|
-
import { computeContextDiff } from '../../sync/diff.js';
|
|
27
|
-
import { extractUlidFromFilename } from '../../utils/naming.js';
|
|
23
|
+
import { inspectArticleDiff } from '../../sync/diff.js';
|
|
24
|
+
import { formatToolError } from '../tool-errors.js';
|
|
28
25
|
export function registerSyncDiffTool(server, resolveContext) {
|
|
29
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.', {
|
|
30
27
|
filePath: z
|
|
@@ -34,79 +31,30 @@ export function registerSyncDiffTool(server, resolveContext) {
|
|
|
34
31
|
id: z.string().optional().describe('Article ID (ULID) to inspect'),
|
|
35
32
|
profile: z.string().optional().describe('Target profile name for multi-site setups'),
|
|
36
33
|
}, async (args) => {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
if (!targetId && targetFile) {
|
|
41
|
-
const full = path.join(ctx.root, targetFile);
|
|
42
|
-
if (fs.existsSync(full)) {
|
|
43
|
-
const ulid = extractUlidFromFilename(full);
|
|
44
|
-
if (ulid)
|
|
45
|
-
targetId = ulid;
|
|
46
|
-
}
|
|
34
|
+
let ctx;
|
|
35
|
+
try {
|
|
36
|
+
ctx = resolveContext(args.profile);
|
|
47
37
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
if (syncState)
|
|
51
|
-
targetFile = syncState.localFilePath;
|
|
38
|
+
catch (error) {
|
|
39
|
+
return formatToolError(error);
|
|
52
40
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
};
|
|
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
|
+
});
|
|
62
49
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
return {
|
|
66
|
-
content: [
|
|
67
|
-
{
|
|
68
|
-
type: 'text',
|
|
69
|
-
text: `❌ Local file not found: ${targetFile}`,
|
|
70
|
-
},
|
|
71
|
-
],
|
|
72
|
-
};
|
|
50
|
+
catch (error) {
|
|
51
|
+
return formatToolError(error);
|
|
73
52
|
}
|
|
74
|
-
const localContent = fs.readFileSync(fullLocalPath, 'utf8');
|
|
75
|
-
const baseSnapshot = ctx.cache.getBaseSnapshot(targetId);
|
|
76
|
-
if (!baseSnapshot) {
|
|
77
|
-
return {
|
|
78
|
-
content: [
|
|
79
|
-
{
|
|
80
|
-
type: 'text',
|
|
81
|
-
text: `ℹ️ No base snapshot found for ID "${targetId}". Article is untracked or newly created.`,
|
|
82
|
-
},
|
|
83
|
-
],
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
const syncState = ctx.cache.getSyncState(targetId);
|
|
87
|
-
const currentHash = crypto.createHash('sha256').update(localContent, 'utf8').digest('hex');
|
|
88
|
-
const isModified = syncState ? syncState.localHash !== currentHash : true;
|
|
89
|
-
const baseFullMarkdown = `---\n${baseSnapshot.frontmatterYaml}---\n${baseSnapshot.bodyMarkdown}`;
|
|
90
|
-
const diffResult = computeContextDiff(baseFullMarkdown, localContent, {
|
|
91
|
-
baseLabel: `base [rev: ${baseSnapshot.rev}]`,
|
|
92
|
-
localLabel: `local [${targetFile}]`,
|
|
93
|
-
});
|
|
94
53
|
return {
|
|
95
54
|
content: [
|
|
96
55
|
{
|
|
97
56
|
type: 'text',
|
|
98
|
-
text:
|
|
99
|
-
`--- Diff for ${targetFile} (${targetId}) ---`,
|
|
100
|
-
`Status: ${isModified ? '🟡 Modified' : '🟢 In Sync with base snapshot'}`,
|
|
101
|
-
`Base Rev: ${baseSnapshot.rev}`,
|
|
102
|
-
`Base Saved At: ${new Date(baseSnapshot.savedAt).toISOString()}`,
|
|
103
|
-
`Changes: +${diffResult.additions} / -${diffResult.deletions} lines`,
|
|
104
|
-
'',
|
|
105
|
-
'Unified Diff:',
|
|
106
|
-
'----------------------------------------',
|
|
107
|
-
diffResult.unifiedDiff,
|
|
108
|
-
'----------------------------------------',
|
|
109
|
-
].join('\n'),
|
|
57
|
+
text: inspection.formattedOutput,
|
|
110
58
|
},
|
|
111
59
|
],
|
|
112
60
|
};
|
|
@@ -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;
|
|
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,CAAC,CAAC;QAChC,CAAC;QAED,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 +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,
|
|
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;AAKpE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,eAAe,GAAG,IAAI,CAwD5F"}
|
|
@@ -22,8 +22,9 @@
|
|
|
22
22
|
import { z } from 'zod';
|
|
23
23
|
import { createArticleScaffold } 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
|
-
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 so you can edit the Markdown file directly before pushing.', {
|
|
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'),
|
|
28
29
|
title: z.string().optional().describe('Article title'),
|
|
29
30
|
collection: z
|
|
@@ -31,28 +32,46 @@ export function registerSyncNewTool(server, resolveContext) {
|
|
|
31
32
|
.optional()
|
|
32
33
|
.describe('Target collection (defaults to "posts" or config)'),
|
|
33
34
|
locale: z.string().optional().describe('Article locale (defaults to "ja")'),
|
|
35
|
+
byline: z
|
|
36
|
+
.string()
|
|
37
|
+
.optional()
|
|
38
|
+
.describe('Author byline slug (defaults to first cached non-guest author by slug)'),
|
|
34
39
|
profile: z.string().optional().describe('Target profile name for multi-site setups'),
|
|
35
40
|
}, async (args) => {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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
|
+
const res = createArticleScaffold({
|
|
51
|
+
slug: args.slug,
|
|
52
|
+
workspaceRoot: ctx.root,
|
|
53
|
+
collection,
|
|
54
|
+
title: args.title,
|
|
55
|
+
locale: args.locale || ctx.config.defaultLocale,
|
|
56
|
+
byline: args.byline,
|
|
57
|
+
cache: ctx.cache,
|
|
58
|
+
});
|
|
59
|
+
const taxSummary = getLocalTaxonomiesSummary(ctx.root);
|
|
60
|
+
const taxHint = formatTaxonomiesHint(taxSummary, { maxTags: 60 });
|
|
61
|
+
const hintBlock = taxHint ? `\n\n${taxHint}` : '';
|
|
62
|
+
return {
|
|
63
|
+
content: [
|
|
64
|
+
{
|
|
65
|
+
type: 'text',
|
|
66
|
+
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.`,
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
// Slug validation, byline resolution, and taxonomy hint reads all fail here.
|
|
73
|
+
return formatToolError(error);
|
|
74
|
+
}
|
|
56
75
|
});
|
|
57
76
|
}
|
|
58
77
|
//# 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;
|
|
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;AAC3F,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,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,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,CAAC;YACnE,MAAM,GAAG,GAAG,qBAAqB,CAAC;gBAChC,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,aAAa,EAAE,GAAG,CAAC,IAAI;gBACvB,UAAU;gBACV,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,aAAa;gBAC/C,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,KAAK,EAAE,GAAG,CAAC,KAAK;aACjB,CAAC,CAAC;YAEH,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,MAAM,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,OAAO,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAElD,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,gCAAgC,IAAI,CAAC,IAAI,UAAU,GAAG,CAAC,EAAE,QAAQ,GAAG,CAAC,QAAQ,IAAI,SAAS,oEAAoE;qBACrK;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,6EAA6E;YAC7E,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync-pull.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/sync-pull.ts"],"names":[],"mappings":"
|
|
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,CA2R9F"}
|