@shrkcrft/mcp-server 0.1.0-alpha.1 → 0.1.0-alpha.11
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 +1 -1
- package/dist/main.d.ts +1 -1
- package/dist/main.js +1 -1
- package/dist/server/create-mcp-server.d.ts.map +1 -1
- package/dist/server/create-mcp-server.js +21 -15
- package/dist/server/http-transport.d.ts +2 -7
- package/dist/server/http-transport.d.ts.map +1 -1
- package/dist/server/http-transport.js +6 -10
- package/dist/tools/all-tools.d.ts.map +1 -1
- package/dist/tools/all-tools.js +49 -7
- package/dist/tools/diff-check.tool.d.ts +15 -0
- package/dist/tools/diff-check.tool.d.ts.map +1 -0
- package/dist/tools/diff-check.tool.js +157 -0
- package/dist/tools/file-advice.tool.d.ts +22 -0
- package/dist/tools/file-advice.tool.d.ts.map +1 -0
- package/dist/tools/file-advice.tool.js +88 -0
- package/dist/tools/get-api-surface-diff.tool.d.ts +3 -0
- package/dist/tools/get-api-surface-diff.tool.d.ts.map +1 -0
- package/dist/tools/get-api-surface-diff.tool.js +60 -0
- package/dist/tools/get-arch-violations.tool.d.ts +3 -0
- package/dist/tools/get-arch-violations.tool.d.ts.map +1 -0
- package/dist/tools/get-arch-violations.tool.js +30 -0
- package/dist/tools/get-code-intelligence-state.tool.d.ts +11 -0
- package/dist/tools/get-code-intelligence-state.tool.d.ts.map +1 -0
- package/dist/tools/get-code-intelligence-state.tool.js +59 -0
- package/dist/tools/get-context-pack.tool.d.ts +3 -0
- package/dist/tools/get-context-pack.tool.d.ts.map +1 -0
- package/dist/tools/get-context-pack.tool.js +40 -0
- package/dist/tools/get-framework-entities.tool.d.ts +3 -0
- package/dist/tools/get-framework-entities.tool.d.ts.map +1 -0
- package/dist/tools/get-framework-entities.tool.js +68 -0
- package/dist/tools/get-graph-callers.tool.d.ts +3 -0
- package/dist/tools/get-graph-callers.tool.d.ts.map +1 -0
- package/dist/tools/get-graph-callers.tool.js +80 -0
- package/dist/tools/get-graph-context.tool.d.ts +3 -0
- package/dist/tools/get-graph-context.tool.d.ts.map +1 -0
- package/dist/tools/get-graph-context.tool.js +91 -0
- package/dist/tools/get-graph-cycles.tool.d.ts +10 -0
- package/dist/tools/get-graph-cycles.tool.d.ts.map +1 -0
- package/dist/tools/get-graph-cycles.tool.js +57 -0
- package/dist/tools/get-graph-deps.tool.d.ts +12 -0
- package/dist/tools/get-graph-deps.tool.d.ts.map +1 -0
- package/dist/tools/get-graph-deps.tool.js +80 -0
- package/dist/tools/get-graph-impact-analysis.tool.d.ts +3 -0
- package/dist/tools/get-graph-impact-analysis.tool.d.ts.map +1 -0
- package/dist/tools/get-graph-impact-analysis.tool.js +42 -0
- package/dist/tools/get-graph-impact.tool.d.ts +3 -0
- package/dist/tools/get-graph-impact.tool.d.ts.map +1 -0
- package/dist/tools/get-graph-impact.tool.js +127 -0
- package/dist/tools/get-graph-search.tool.d.ts +3 -0
- package/dist/tools/get-graph-search.tool.d.ts.map +1 -0
- package/dist/tools/get-graph-search.tool.js +75 -0
- package/dist/tools/get-graph-status.tool.d.ts +9 -0
- package/dist/tools/get-graph-status.tool.d.ts.map +1 -0
- package/dist/tools/get-graph-status.tool.js +46 -0
- package/dist/tools/get-graph-unresolved.tool.d.ts +11 -0
- package/dist/tools/get-graph-unresolved.tool.d.ts.map +1 -0
- package/dist/tools/get-graph-unresolved.tool.js +81 -0
- package/dist/tools/get-impact-baseline.tool.d.ts +9 -0
- package/dist/tools/get-impact-baseline.tool.d.ts.map +1 -0
- package/dist/tools/get-impact-baseline.tool.js +65 -0
- package/dist/tools/get-intent-benchmark-run.tool.d.ts +12 -0
- package/dist/tools/get-intent-benchmark-run.tool.d.ts.map +1 -0
- package/dist/tools/get-intent-benchmark-run.tool.js +55 -0
- package/dist/tools/get-migrations.tool.d.ts +3 -0
- package/dist/tools/get-migrations.tool.d.ts.map +1 -0
- package/dist/tools/get-migrations.tool.js +70 -0
- package/dist/tools/get-pattern-registry.tool.d.ts +8 -0
- package/dist/tools/get-pattern-registry.tool.d.ts.map +1 -0
- package/dist/tools/get-pattern-registry.tool.js +40 -0
- package/dist/tools/get-quality-gate.tool.d.ts +3 -0
- package/dist/tools/get-quality-gate.tool.d.ts.map +1 -0
- package/dist/tools/get-quality-gate.tool.js +27 -0
- package/dist/tools/get-rules-for-file.tool.d.ts +3 -0
- package/dist/tools/get-rules-for-file.tool.d.ts.map +1 -0
- package/dist/tools/get-rules-for-file.tool.js +54 -0
- package/dist/tools/get-structural-rewrite-plan.tool.d.ts +3 -0
- package/dist/tools/get-structural-rewrite-plan.tool.d.ts.map +1 -0
- package/dist/tools/get-structural-rewrite-plan.tool.js +46 -0
- package/dist/tools/get-structural-search.tool.d.ts +3 -0
- package/dist/tools/get-structural-search.tool.d.ts.map +1 -0
- package/dist/tools/get-structural-search.tool.js +35 -0
- package/dist/tools/primary-tools.d.ts +24 -0
- package/dist/tools/primary-tools.d.ts.map +1 -0
- package/dist/tools/primary-tools.js +70 -0
- package/dist/tools/r19-extras.tool.js +1 -1
- package/dist/tools/r32-profiles.tool.d.ts +0 -3
- package/dist/tools/r32-profiles.tool.d.ts.map +1 -1
- package/dist/tools/r32-profiles.tool.js +3 -54
- package/package.json +31 -20
- package/dist/tools/r28-plugin-lifecycle.tool.d.ts +0 -4
- package/dist/tools/r28-plugin-lifecycle.tool.d.ts.map +0 -1
- package/dist/tools/r28-plugin-lifecycle.tool.js +0 -94
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
SharkCraft MCP server: 25 tools over @modelcontextprotocol/sdk's stdio transport.
|
|
4
4
|
|
|
5
|
-
Part of [SharkCraft](https://github.com/
|
|
5
|
+
Part of [SharkCraft](https://github.com/shrkcrft/sharkcraft) — a deterministic, local-first toolkit that gives AI coding agents durable project context. See the main repo for documentation, examples, and the `shrk` CLI.
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
package/dist/main.d.ts
CHANGED
package/dist/main.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-mcp-server.d.ts","sourceRoot":"","sources":["../../src/server/create-mcp-server.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAQnE,OAAO,EAAqB,KAAK,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"create-mcp-server.d.ts","sourceRoot":"","sources":["../../src/server/create-mcp-server.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAQnE,OAAO,EAAqB,KAAK,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACpF,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EACV,eAAe,EAEf,eAAe,EAChB,MAAM,sBAAsB,CAAC;AAM9B,MAAM,WAAW,qBAAqB;IACpC,0DAA0D;IAC1D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,qEAAqE;IACrE,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC7B,yCAAyC;IACzC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yCAAyC;IACzC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,YAAY,CAAC,EAAE,eAAe,CAAC;CAChC;AAED,MAAM,WAAW,6BAA8B,SAAQ,gBAAgB;IACrE,0DAA0D;IAC1D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sDAAsD;IACtD,YAAY,CAAC,EAAE,eAAe,CAAC;CAChC;AAED,UAAU,WAAW;IACnB,MAAM,EAAE,gBAAgB,CAAC;IACzB,UAAU,EAAE,qBAAqB,GAAG,IAAI,CAAC;IACzC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC1C,mCAAmC;IACnC,YAAY,CAAC,EAAE,eAAe,CAAC;CAChC;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,iBAAiB,EAAE,MAAM,GAAG,SAAS,EACrC,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,GACpD,MAAM,CAIR;AAqBD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,6BAA6B,GAAG;IAC7E,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,WAAW,CAAC;CACpB,CAgIA;AAED,wBAAsB,cAAc,CAAC,OAAO,GAAE,qBAA0B,GAAG,OAAO,CAAC,IAAI,CAAC,CAmEvF"}
|
|
@@ -3,9 +3,9 @@ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
|
3
3
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
4
|
import { CallToolRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, ReadResourceRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
5
5
|
import { inspectSharkcraft } from '@shrkcrft/inspector';
|
|
6
|
-
import { initTokenizer } from '@shrkcrft/context';
|
|
7
6
|
import { MCP_SERVER_NAME, MCP_SERVER_VERSION, } from "./mcp-server-config.js";
|
|
8
7
|
import { ALL_TOOLS } from "../tools/index.js";
|
|
8
|
+
import { PRIMARY_MCP_TOOLS, shouldAdvertiseFullToolset } from "../tools/primary-tools.js";
|
|
9
9
|
import { validateToolInput } from "./tool-input-validators.js";
|
|
10
10
|
import { buildResourceList, readResource } from "../resources/index.js";
|
|
11
11
|
/**
|
|
@@ -53,13 +53,24 @@ export function createSharkcraftServer(config) {
|
|
|
53
53
|
resources: { listChanged: true },
|
|
54
54
|
},
|
|
55
55
|
});
|
|
56
|
-
server.setRequestHandler(ListToolsRequestSchema, async () =>
|
|
57
|
-
tools
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
56
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
57
|
+
// Default `tools/list` advertises only the ~30 primary tools to
|
|
58
|
+
// keep the agent's tool-selection surface focused. The other ~200
|
|
59
|
+
// tools stay CALLABLE via `tools/call` for agents that already
|
|
60
|
+
// know the name (e.g. via `shrk export claude-skill` referencing
|
|
61
|
+
// them). Set SHRK_MCP_FULL_TOOLS=1 to advertise everything.
|
|
62
|
+
const advertiseFull = shouldAdvertiseFullToolset();
|
|
63
|
+
const advertised = advertiseFull
|
|
64
|
+
? ALL_TOOLS
|
|
65
|
+
: ALL_TOOLS.filter((t) => PRIMARY_MCP_TOOLS.has(t.name));
|
|
66
|
+
return {
|
|
67
|
+
tools: advertised.map((t) => ({
|
|
68
|
+
name: t.name,
|
|
69
|
+
description: t.description,
|
|
70
|
+
inputSchema: t.inputSchema,
|
|
71
|
+
})),
|
|
72
|
+
};
|
|
73
|
+
});
|
|
63
74
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
64
75
|
const name = request.params.name;
|
|
65
76
|
const args = (request.params.arguments ?? {});
|
|
@@ -141,11 +152,6 @@ export function createSharkcraftServer(config) {
|
|
|
141
152
|
export async function startMcpServer(options = {}) {
|
|
142
153
|
const cwd = resolveTargetRoot(options.cwd, options.projectRoot);
|
|
143
154
|
const verbose = options.verbose ?? false;
|
|
144
|
-
// Best-effort upgrade from the estimator to gpt-tokenizer. Failure leaves
|
|
145
|
-
// the estimator active — the server still serves requests.
|
|
146
|
-
if (process.env.SHARKCRAFT_NO_REAL_TOKENIZER !== '1') {
|
|
147
|
-
initTokenizer().catch(() => undefined);
|
|
148
|
-
}
|
|
149
155
|
const { server, state } = createSharkcraftServer({
|
|
150
156
|
name: MCP_SERVER_NAME,
|
|
151
157
|
version: MCP_SERVER_VERSION,
|
|
@@ -198,8 +204,8 @@ export async function startMcpServer(options = {}) {
|
|
|
198
204
|
};
|
|
199
205
|
process.on('SIGINT', () => void stop());
|
|
200
206
|
process.on('SIGTERM', () => void stop());
|
|
201
|
-
|
|
202
|
-
|
|
207
|
+
if (verbose)
|
|
208
|
+
process.stderr.write(`[mcp] http endpoint: ${handle.url}\n`);
|
|
203
209
|
return;
|
|
204
210
|
}
|
|
205
211
|
const transport = new StdioServerTransport();
|
|
@@ -2,9 +2,9 @@ import type { Server as McpServer } from '@modelcontextprotocol/sdk/server/index
|
|
|
2
2
|
export interface StartHttpServerOptions {
|
|
3
3
|
/** McpServer (NOT yet connected). */
|
|
4
4
|
server: McpServer;
|
|
5
|
-
/** Bind host. Default '
|
|
5
|
+
/** Bind host. Default 'localhost'. */
|
|
6
6
|
host?: string;
|
|
7
|
-
/** Bind port. Default
|
|
7
|
+
/** Bind port. Default 4000. */
|
|
8
8
|
port?: number;
|
|
9
9
|
/** Path that accepts MCP traffic. Default '/mcp'. */
|
|
10
10
|
path?: string;
|
|
@@ -17,12 +17,7 @@ export interface StartHttpServerOptions {
|
|
|
17
17
|
log?: (line: string) => void;
|
|
18
18
|
}
|
|
19
19
|
export interface HttpServerHandle {
|
|
20
|
-
/** Full URL clients should POST to (host:port + path). */
|
|
21
20
|
url: string;
|
|
22
|
-
/** The host the server is actually bound to. */
|
|
23
|
-
host: string;
|
|
24
|
-
/** The port the server is actually bound to (resolved when port=0). */
|
|
25
|
-
port: number;
|
|
26
21
|
close: () => Promise<void>;
|
|
27
22
|
}
|
|
28
23
|
export declare function startHttpServer(options: StartHttpServerOptions): Promise<HttpServerHandle>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-transport.d.ts","sourceRoot":"","sources":["../../src/server/http-transport.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"http-transport.d.ts","sourceRoot":"","sources":["../../src/server/http-transport.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,2CAA2C,CAAC;AAErF,MAAM,WAAW,sBAAsB;IACrC,qCAAqC;IACrC,MAAM,EAAE,SAAS,CAAC;IAClB,sCAAsC;IACtC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+BAA+B;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qDAAqD;IACrD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qBAAqB;IACrB,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B;AAsBD,wBAAsB,eAAe,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAmDhG"}
|
|
@@ -22,8 +22,8 @@ function writeJson(res, status, body) {
|
|
|
22
22
|
res.end(JSON.stringify(body));
|
|
23
23
|
}
|
|
24
24
|
export async function startHttpServer(options) {
|
|
25
|
-
const host = options.host ?? '
|
|
26
|
-
const
|
|
25
|
+
const host = options.host ?? 'localhost';
|
|
26
|
+
const port = options.port ?? 4000;
|
|
27
27
|
const path = options.path ?? '/mcp';
|
|
28
28
|
const stateful = options.stateful ?? true;
|
|
29
29
|
const log = options.log ?? (() => undefined);
|
|
@@ -40,7 +40,7 @@ export async function startHttpServer(options) {
|
|
|
40
40
|
writeJson(res, 200, { ok: true, transport: 'streamable-http', stateful });
|
|
41
41
|
return;
|
|
42
42
|
}
|
|
43
|
-
const url = new URL(req.url, `http://${host}:${
|
|
43
|
+
const url = new URL(req.url, `http://${host}:${port}`);
|
|
44
44
|
if (url.pathname !== path) {
|
|
45
45
|
writeJson(res, 404, { error: `not found: ${url.pathname}` });
|
|
46
46
|
return;
|
|
@@ -59,14 +59,10 @@ export async function startHttpServer(options) {
|
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
});
|
|
62
|
-
await new Promise((resolve) => http.listen(
|
|
63
|
-
|
|
64
|
-
const actualPort = address?.port ?? requestedPort;
|
|
65
|
-
log(`[mcp:http] listening on http://${host}:${actualPort}${path} (stateful=${stateful})`);
|
|
62
|
+
await new Promise((resolve) => http.listen(port, host, resolve));
|
|
63
|
+
log(`[mcp:http] listening on http://${host}:${port}${path} (stateful=${stateful})`);
|
|
66
64
|
return {
|
|
67
|
-
url: `http://${host}:${
|
|
68
|
-
host,
|
|
69
|
-
port: actualPort,
|
|
65
|
+
url: `http://${host}:${port}${path}`,
|
|
70
66
|
close: async () => {
|
|
71
67
|
await transport.close().catch(() => undefined);
|
|
72
68
|
await new Promise((resolve, reject) => http.close((err) => (err ? reject(err) : resolve())));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"all-tools.d.ts","sourceRoot":"","sources":["../../src/tools/all-tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"all-tools.d.ts","sourceRoot":"","sources":["../../src/tools/all-tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAuUpE,eAAO,MAAM,SAAS,EAAE,SAAS,eAAe,EAgR9C,CAAC"}
|
package/dist/tools/all-tools.js
CHANGED
|
@@ -42,6 +42,28 @@ import { checkBoundariesTool } from "./check-boundaries.tool.js";
|
|
|
42
42
|
import { listBoundaryRulesTool } from "./list-boundary-rules.tool.js";
|
|
43
43
|
import { getBoundaryRuleTool } from "./get-boundary-rule.tool.js";
|
|
44
44
|
import { getImportGraphSummaryTool } from "./get-import-graph-summary.tool.js";
|
|
45
|
+
import { getGraphStatusTool } from "./get-graph-status.tool.js";
|
|
46
|
+
import { getGraphSearchTool } from "./get-graph-search.tool.js";
|
|
47
|
+
import { getGraphContextTool } from "./get-graph-context.tool.js";
|
|
48
|
+
import { getGraphImpactTool } from "./get-graph-impact.tool.js";
|
|
49
|
+
import { getGraphCallersTool } from "./get-graph-callers.tool.js";
|
|
50
|
+
import { getGraphCyclesTool } from "./get-graph-cycles.tool.js";
|
|
51
|
+
import { getGraphUnresolvedTool } from "./get-graph-unresolved.tool.js";
|
|
52
|
+
import { getGraphDepsTool } from "./get-graph-deps.tool.js";
|
|
53
|
+
import { getImpactBaselineTool } from "./get-impact-baseline.tool.js";
|
|
54
|
+
import { getPatternRegistryTool } from "./get-pattern-registry.tool.js";
|
|
55
|
+
import { getIntentBenchmarkRunTool } from "./get-intent-benchmark-run.tool.js";
|
|
56
|
+
import { getCodeIntelligenceStateTool } from "./get-code-intelligence-state.tool.js";
|
|
57
|
+
import { getRulesForFileTool } from "./get-rules-for-file.tool.js";
|
|
58
|
+
import { getStructuralSearchTool } from "./get-structural-search.tool.js";
|
|
59
|
+
import { getStructuralRewritePlanTool } from "./get-structural-rewrite-plan.tool.js";
|
|
60
|
+
import { getGraphImpactAnalysisTool } from "./get-graph-impact-analysis.tool.js";
|
|
61
|
+
import { getContextPackTool } from "./get-context-pack.tool.js";
|
|
62
|
+
import { getArchViolationsTool } from "./get-arch-violations.tool.js";
|
|
63
|
+
import { getFrameworkEntitiesTool } from "./get-framework-entities.tool.js";
|
|
64
|
+
import { getApiSurfaceDiffTool } from "./get-api-surface-diff.tool.js";
|
|
65
|
+
import { getQualityGateTool } from "./get-quality-gate.tool.js";
|
|
66
|
+
import { getMigrationsTool } from "./get-migrations.tool.js";
|
|
45
67
|
import { getDriftReportTool } from "./get-drift-report.tool.js";
|
|
46
68
|
import { getKnowledgeGraphTool } from "./get-knowledge-graph.tool.js";
|
|
47
69
|
import { getGraphNodeTool } from "./get-graph-node.tool.js";
|
|
@@ -116,7 +138,8 @@ import { getContractTemplateTool, getLanguageCommandsTool, getLanguageProfilesTo
|
|
|
116
138
|
import { getTaskContextTool, understandTaskTool, validateChangeContextTool, } from "./r26-task-context.tool.js";
|
|
117
139
|
import { getLanguageCacheStatusTool, getLanguageProfilesLiveTool, getLanguageRunPlanTool, getPolyglotBoundaryReportTool, } from "./r27-polyglot.tool.js";
|
|
118
140
|
import { getChangedBoundaryReportTool } from "./r28-changed-boundary.tool.js";
|
|
119
|
-
import {
|
|
141
|
+
import { getDiffCheckReportTool } from "./diff-check.tool.js";
|
|
142
|
+
import { getFileAdviceTool } from "./file-advice.tool.js";
|
|
120
143
|
import { getHelperTool, listHelpersTool, previewHelperPlanTool } from "./r28-helpers.tool.js";
|
|
121
144
|
import { getPackDevStatusTool, previewPackTestsTool } from "./r28-pack-author.tool.js";
|
|
122
145
|
import { getRegistryLifecycleReportTool } from "./r28-registry-lifecycle.tool.js";
|
|
@@ -135,7 +158,7 @@ import { suggestCommandsTool, searchCommandsTool, explainCommandTool, } from "./
|
|
|
135
158
|
import { previewFixTool, listFixKindsTool, } from "./r31-fix-preview.tool.js";
|
|
136
159
|
import { getScaffoldCoverageReportTool } from "./r31-scaffold-coverage.tool.js";
|
|
137
160
|
import { getChangesSummaryTool, getPrSummaryPreviewTool, getCiIntegrityReportTool, } from "./r31-changes-pr-ci.tool.js";
|
|
138
|
-
import { listProfilesTool, getProfileTool, getProfilesDoctorTool,
|
|
161
|
+
import { listProfilesTool, getProfileTool, getProfilesDoctorTool, } from "./r32-profiles.tool.js";
|
|
139
162
|
import { getProjectCouplingReportTool } from "./r32-project-coupling.tool.js";
|
|
140
163
|
import { getPackContributionsTool, getPackConflictsTool, } from "./r33-pack-contributions.tool.js";
|
|
141
164
|
import { listConventionsTool, getConventionTool, getConventionsDoctorTool, } from "./r33-conventions.tool.js";
|
|
@@ -192,6 +215,28 @@ export const ALL_TOOLS = Object.freeze([
|
|
|
192
215
|
listBoundaryRulesTool,
|
|
193
216
|
getBoundaryRuleTool,
|
|
194
217
|
getImportGraphSummaryTool,
|
|
218
|
+
getGraphStatusTool,
|
|
219
|
+
getGraphSearchTool,
|
|
220
|
+
getGraphContextTool,
|
|
221
|
+
getGraphImpactTool,
|
|
222
|
+
getGraphCallersTool,
|
|
223
|
+
getGraphCyclesTool,
|
|
224
|
+
getGraphUnresolvedTool,
|
|
225
|
+
getGraphDepsTool,
|
|
226
|
+
getImpactBaselineTool,
|
|
227
|
+
getPatternRegistryTool,
|
|
228
|
+
getIntentBenchmarkRunTool,
|
|
229
|
+
getCodeIntelligenceStateTool,
|
|
230
|
+
getRulesForFileTool,
|
|
231
|
+
getStructuralSearchTool,
|
|
232
|
+
getStructuralRewritePlanTool,
|
|
233
|
+
getGraphImpactAnalysisTool,
|
|
234
|
+
getContextPackTool,
|
|
235
|
+
getArchViolationsTool,
|
|
236
|
+
getFrameworkEntitiesTool,
|
|
237
|
+
getApiSurfaceDiffTool,
|
|
238
|
+
getQualityGateTool,
|
|
239
|
+
getMigrationsTool,
|
|
195
240
|
getDriftReportTool,
|
|
196
241
|
getKnowledgeGraphTool,
|
|
197
242
|
getGraphNodeTool,
|
|
@@ -334,8 +379,8 @@ export const ALL_TOOLS = Object.freeze([
|
|
|
334
379
|
getLanguageCacheStatusTool,
|
|
335
380
|
getLanguageProfilesLiveTool,
|
|
336
381
|
getChangedBoundaryReportTool,
|
|
337
|
-
|
|
338
|
-
|
|
382
|
+
getDiffCheckReportTool,
|
|
383
|
+
getFileAdviceTool,
|
|
339
384
|
listHelpersTool,
|
|
340
385
|
getHelperTool,
|
|
341
386
|
previewHelperPlanTool,
|
|
@@ -370,9 +415,6 @@ export const ALL_TOOLS = Object.freeze([
|
|
|
370
415
|
listProfilesTool,
|
|
371
416
|
getProfileTool,
|
|
372
417
|
getProfilesDoctorTool,
|
|
373
|
-
listPluginLifecycleProfilesTool,
|
|
374
|
-
getPluginLifecycleProfileTool,
|
|
375
|
-
getPluginLifecycleProfileDoctorTool,
|
|
376
418
|
getProjectCouplingReportTool,
|
|
377
419
|
getPackContributionsTool,
|
|
378
420
|
getPackConflictsTool,
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read-only MCP tool: get_diff_check_report.
|
|
3
|
+
*
|
|
4
|
+
* The MCP-side mirror of `shrk diff-check`. Same envelope, same
|
|
5
|
+
* verdict logic — the agent gets a single structured answer to "did
|
|
6
|
+
* my edits pass this project's boundary + import-hygiene gates?".
|
|
7
|
+
*
|
|
8
|
+
* Still read-only: this tool DOES NOT fix anything, even when it
|
|
9
|
+
* could trivially suggest the fix. The agent reads the envelope, then
|
|
10
|
+
* the human (or the agent, via a separate write-path tool) runs the
|
|
11
|
+
* fix on the CLI. Keeps the safety contract intact.
|
|
12
|
+
*/
|
|
13
|
+
import type { IToolDefinition } from '../server/tool-definition.js';
|
|
14
|
+
export declare const getDiffCheckReportTool: IToolDefinition;
|
|
15
|
+
//# sourceMappingURL=diff-check.tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-check.tool.d.ts","sourceRoot":"","sources":["../../src/tools/diff-check.tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAaH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAyBpE,eAAO,MAAM,sBAAsB,EAAE,eAyHpC,CAAC"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read-only MCP tool: get_diff_check_report.
|
|
3
|
+
*
|
|
4
|
+
* The MCP-side mirror of `shrk diff-check`. Same envelope, same
|
|
5
|
+
* verdict logic — the agent gets a single structured answer to "did
|
|
6
|
+
* my edits pass this project's boundary + import-hygiene gates?".
|
|
7
|
+
*
|
|
8
|
+
* Still read-only: this tool DOES NOT fix anything, even when it
|
|
9
|
+
* could trivially suggest the fix. The agent reads the envelope, then
|
|
10
|
+
* the human (or the agent, via a separate write-path tool) runs the
|
|
11
|
+
* fix on the CLI. Keeps the safety contract intact.
|
|
12
|
+
*/
|
|
13
|
+
import { buildImportHygieneReport, filterViolationsToChangedScope, resolveChangedFiles, } from '@shrkcrft/inspector';
|
|
14
|
+
import { evaluateBoundaries, loadTsconfigPaths, scanImports, } from '@shrkcrft/boundaries';
|
|
15
|
+
const SCHEMA = 'sharkcraft.diff-check/v1';
|
|
16
|
+
function resolveScopeFromInput(input, cwd) {
|
|
17
|
+
const staged = input.staged === true;
|
|
18
|
+
const since = typeof input.since === 'string' ? input.since : undefined;
|
|
19
|
+
const files = Array.isArray(input.files)
|
|
20
|
+
? input.files.filter((f) => typeof f === 'string')
|
|
21
|
+
: [];
|
|
22
|
+
if (files.length > 0) {
|
|
23
|
+
return { mode: 'files', options: { projectRoot: cwd, files } };
|
|
24
|
+
}
|
|
25
|
+
if (staged) {
|
|
26
|
+
return { mode: 'staged', options: { projectRoot: cwd, staged: true } };
|
|
27
|
+
}
|
|
28
|
+
if (since) {
|
|
29
|
+
return { mode: 'since', options: { projectRoot: cwd, since } };
|
|
30
|
+
}
|
|
31
|
+
return { mode: 'worktree', options: { projectRoot: cwd, includeWorktree: true } };
|
|
32
|
+
}
|
|
33
|
+
export const getDiffCheckReportTool = {
|
|
34
|
+
name: 'get_diff_check_report',
|
|
35
|
+
description: 'Self-check the current git diff against this project\'s boundary + import-hygiene rules. Single-call composite of the boundary-check and import-hygiene engines, scoped to the changed files, with one verdict (ok | warnings | errors) and one nextAction line. Use after editing code so you can validate before declaring done. Read-only.',
|
|
36
|
+
inputSchema: {
|
|
37
|
+
type: 'object',
|
|
38
|
+
additionalProperties: false,
|
|
39
|
+
properties: {
|
|
40
|
+
staged: { type: 'boolean', description: 'Scope to staged changes only.' },
|
|
41
|
+
since: { type: 'string', description: 'Compare against ref (HEAD, origin/main, SHA).' },
|
|
42
|
+
files: {
|
|
43
|
+
type: 'array',
|
|
44
|
+
items: { type: 'string' },
|
|
45
|
+
description: 'Explicit file list (overrides --staged / --since).',
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
async handler(input, ctx) {
|
|
50
|
+
const cwd = ctx.cwd;
|
|
51
|
+
const { mode, options: scopeOptions } = resolveScopeFromInput(input, cwd);
|
|
52
|
+
const changed = resolveChangedFiles(scopeOptions);
|
|
53
|
+
const changedFiles = changed.files;
|
|
54
|
+
const rules = ctx.inspection.boundaryRegistry.list();
|
|
55
|
+
let boundaryBlock = {
|
|
56
|
+
ran: false,
|
|
57
|
+
rulesEvaluated: 0,
|
|
58
|
+
counts: { error: 0, warning: 0, info: 0 },
|
|
59
|
+
violations: [],
|
|
60
|
+
};
|
|
61
|
+
if (rules.length > 0 && changedFiles.length > 0) {
|
|
62
|
+
const scan = scanImports({ projectRoot: cwd });
|
|
63
|
+
const tsconfigPaths = loadTsconfigPaths(cwd);
|
|
64
|
+
const evalResult = evaluateBoundaries(scan, rules, {
|
|
65
|
+
...(tsconfigPaths.aliases.size > 0 ? { tsconfigPaths } : {}),
|
|
66
|
+
});
|
|
67
|
+
const filtered = filterViolationsToChangedScope(evalResult.violations, scopeOptions);
|
|
68
|
+
boundaryBlock = {
|
|
69
|
+
ran: true,
|
|
70
|
+
rulesEvaluated: evalResult.rulesEvaluated,
|
|
71
|
+
counts: {
|
|
72
|
+
error: filtered.includedViolations.filter((v) => v.severity === 'error').length,
|
|
73
|
+
warning: filtered.includedViolations.filter((v) => v.severity === 'warning').length,
|
|
74
|
+
info: filtered.includedViolations.filter((v) => v.severity === 'info').length,
|
|
75
|
+
},
|
|
76
|
+
violations: filtered.includedViolations,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
else if (rules.length > 0) {
|
|
80
|
+
boundaryBlock = { ...boundaryBlock, ran: true, rulesEvaluated: rules.length };
|
|
81
|
+
}
|
|
82
|
+
let importsBlock = {
|
|
83
|
+
ran: false,
|
|
84
|
+
verdict: 'skipped',
|
|
85
|
+
counts: {},
|
|
86
|
+
findings: [],
|
|
87
|
+
};
|
|
88
|
+
if (changedFiles.length > 0) {
|
|
89
|
+
const report = buildImportHygieneReport(cwd, { files: changedFiles });
|
|
90
|
+
importsBlock = {
|
|
91
|
+
ran: true,
|
|
92
|
+
verdict: report.verdict,
|
|
93
|
+
counts: report.counts ?? {},
|
|
94
|
+
findings: report.findings,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
// Derive verdict — same logic as the CLI command, duplicated
|
|
98
|
+
// intentionally to keep the MCP tool self-contained (no CLI
|
|
99
|
+
// import — preserves the package dependency direction).
|
|
100
|
+
const bErr = boundaryBlock.counts.error;
|
|
101
|
+
const bWarn = boundaryBlock.counts.warning;
|
|
102
|
+
const iErr = importsBlock.verdict === 'errors' ? (importsBlock.counts.error ?? importsBlock.findings.length) : 0;
|
|
103
|
+
const iWarn = importsBlock.verdict === 'warnings' ? (importsBlock.counts.warning ?? importsBlock.findings.length) : 0;
|
|
104
|
+
let verdict;
|
|
105
|
+
let summary;
|
|
106
|
+
let nextAction;
|
|
107
|
+
if (changedFiles.length === 0) {
|
|
108
|
+
verdict = 'ok';
|
|
109
|
+
summary = 'No files changed in the current diff scope.';
|
|
110
|
+
nextAction =
|
|
111
|
+
'Nothing to check. If you expected changes, verify the `staged` / `since` argument or save edits first.';
|
|
112
|
+
}
|
|
113
|
+
else if (bErr > 0 || iErr > 0) {
|
|
114
|
+
verdict = 'errors';
|
|
115
|
+
const parts = [];
|
|
116
|
+
if (bErr > 0)
|
|
117
|
+
parts.push(`${bErr} boundary violation${bErr === 1 ? '' : 's'}`);
|
|
118
|
+
if (iErr > 0)
|
|
119
|
+
parts.push(`${iErr} import-hygiene error${iErr === 1 ? '' : 's'}`);
|
|
120
|
+
summary = `Diff fails the gate: ${parts.join(', ')}.`;
|
|
121
|
+
nextAction =
|
|
122
|
+
'Fix every error in `boundaries.violations` and `imports.findings` (each entry\'s `suggestedFix` shows the fix), then re-run.';
|
|
123
|
+
}
|
|
124
|
+
else if (bWarn > 0 || iWarn > 0) {
|
|
125
|
+
verdict = 'warnings';
|
|
126
|
+
const parts = [];
|
|
127
|
+
if (bWarn > 0)
|
|
128
|
+
parts.push(`${bWarn} boundary warning${bWarn === 1 ? '' : 's'}`);
|
|
129
|
+
if (iWarn > 0)
|
|
130
|
+
parts.push(`${iWarn} import-hygiene warning${iWarn === 1 ? '' : 's'}`);
|
|
131
|
+
summary = `Diff passes the gate with ${parts.join(', ')}.`;
|
|
132
|
+
nextAction = 'Safe to declare done. Review warnings if the diff touches a sensitive area.';
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
verdict = 'ok';
|
|
136
|
+
summary = `Diff passes the gate (${changedFiles.length} file${changedFiles.length === 1 ? '' : 's'}, 0 violations).`;
|
|
137
|
+
nextAction = 'Safe to declare done.';
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
text: `verdict=${verdict}. ${summary} ${nextAction}`,
|
|
141
|
+
data: {
|
|
142
|
+
schema: SCHEMA,
|
|
143
|
+
generatedAt: new Date().toISOString(),
|
|
144
|
+
scope: {
|
|
145
|
+
mode,
|
|
146
|
+
files: changedFiles,
|
|
147
|
+
fileCount: changedFiles.length,
|
|
148
|
+
},
|
|
149
|
+
boundaries: boundaryBlock,
|
|
150
|
+
imports: importsBlock,
|
|
151
|
+
verdict,
|
|
152
|
+
summary,
|
|
153
|
+
nextAction,
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
},
|
|
157
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read-only MCP tool: get_file_advice.
|
|
3
|
+
*
|
|
4
|
+
* For a given file path, returns the rules, path conventions, boundary
|
|
5
|
+
* rules, and knowledge entries that apply to it. The agent equivalent
|
|
6
|
+
* of `shrk why <file>` — same engine (`buildWhyReport`), shaped for
|
|
7
|
+
* MCP consumption.
|
|
8
|
+
*
|
|
9
|
+
* Why this exists alongside `inspect_workspace` and the various
|
|
10
|
+
* `list_*` tools: agents tend to over-explore when given browsable
|
|
11
|
+
* catalogs. Asking "give me everything for this file" in one call
|
|
12
|
+
* keeps the prompt window tight and the answer focused — the agent
|
|
13
|
+
* doesn't have to discover which rule matches the file's path glob,
|
|
14
|
+
* which boundary rule constrains its imports, or which knowledge
|
|
15
|
+
* entry is the right one to read first.
|
|
16
|
+
*
|
|
17
|
+
* Use after a `shrk diff-check` flags a violation, or before editing
|
|
18
|
+
* an unfamiliar file. Read-only.
|
|
19
|
+
*/
|
|
20
|
+
import type { IToolDefinition } from '../server/tool-definition.js';
|
|
21
|
+
export declare const getFileAdviceTool: IToolDefinition;
|
|
22
|
+
//# sourceMappingURL=file-advice.tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-advice.tool.d.ts","sourceRoot":"","sources":["../../src/tools/file-advice.tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAEpE,eAAO,MAAM,iBAAiB,EAAE,eAyC/B,CAAC"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read-only MCP tool: get_file_advice.
|
|
3
|
+
*
|
|
4
|
+
* For a given file path, returns the rules, path conventions, boundary
|
|
5
|
+
* rules, and knowledge entries that apply to it. The agent equivalent
|
|
6
|
+
* of `shrk why <file>` — same engine (`buildWhyReport`), shaped for
|
|
7
|
+
* MCP consumption.
|
|
8
|
+
*
|
|
9
|
+
* Why this exists alongside `inspect_workspace` and the various
|
|
10
|
+
* `list_*` tools: agents tend to over-explore when given browsable
|
|
11
|
+
* catalogs. Asking "give me everything for this file" in one call
|
|
12
|
+
* keeps the prompt window tight and the answer focused — the agent
|
|
13
|
+
* doesn't have to discover which rule matches the file's path glob,
|
|
14
|
+
* which boundary rule constrains its imports, or which knowledge
|
|
15
|
+
* entry is the right one to read first.
|
|
16
|
+
*
|
|
17
|
+
* Use after a `shrk diff-check` flags a violation, or before editing
|
|
18
|
+
* an unfamiliar file. Read-only.
|
|
19
|
+
*/
|
|
20
|
+
import { buildWhyReport } from '@shrkcrft/inspector';
|
|
21
|
+
export const getFileAdviceTool = {
|
|
22
|
+
name: 'get_file_advice',
|
|
23
|
+
description: 'For a given file path, return the rules, path conventions, boundary rules, and knowledge entries that apply to it. Single-call replacement for browsing the registry to figure out what constrains one file. Read-only.',
|
|
24
|
+
inputSchema: {
|
|
25
|
+
type: 'object',
|
|
26
|
+
additionalProperties: false,
|
|
27
|
+
required: ['file'],
|
|
28
|
+
properties: {
|
|
29
|
+
file: {
|
|
30
|
+
type: 'string',
|
|
31
|
+
description: 'Path to the file (absolute, or relative to the project root). The file does not need to exist — path-string matching still works.',
|
|
32
|
+
},
|
|
33
|
+
limit: {
|
|
34
|
+
type: 'number',
|
|
35
|
+
description: 'Cap rules and knowledge entries returned (default 10).',
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
async handler(input, ctx) {
|
|
40
|
+
const file = typeof input.file === 'string' ? input.file : '';
|
|
41
|
+
if (!file) {
|
|
42
|
+
return {
|
|
43
|
+
text: 'Error: `file` argument is required.',
|
|
44
|
+
data: { error: 'missing-argument', argument: 'file' },
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
const limit = typeof input.limit === 'number' && input.limit > 0 ? Math.floor(input.limit) : 10;
|
|
48
|
+
const report = buildWhyReport({
|
|
49
|
+
inspection: ctx.inspection,
|
|
50
|
+
projectRoot: ctx.cwd,
|
|
51
|
+
target: file,
|
|
52
|
+
limit,
|
|
53
|
+
});
|
|
54
|
+
const summary = buildSummary(report);
|
|
55
|
+
return {
|
|
56
|
+
text: summary,
|
|
57
|
+
data: report,
|
|
58
|
+
};
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
function buildSummary(report) {
|
|
62
|
+
const lines = [];
|
|
63
|
+
lines.push(`File: ${report.target.relativePath} (${report.target.kind})`);
|
|
64
|
+
if (report.inferredPackage)
|
|
65
|
+
lines.push(`Package: ${report.inferredPackage}`);
|
|
66
|
+
if (report.inferredLayer)
|
|
67
|
+
lines.push(`Layer: ${report.inferredLayer}`);
|
|
68
|
+
const counts = {
|
|
69
|
+
rules: report.rules.length,
|
|
70
|
+
boundaries: report.boundaries.length,
|
|
71
|
+
paths: report.pathConventions.length,
|
|
72
|
+
knowledge: report.knowledge.length,
|
|
73
|
+
};
|
|
74
|
+
lines.push(`Matches: ${counts.rules} rule${counts.rules === 1 ? '' : 's'}, ` +
|
|
75
|
+
`${counts.boundaries} boundary rule${counts.boundaries === 1 ? '' : 's'}, ` +
|
|
76
|
+
`${counts.paths} path convention${counts.paths === 1 ? '' : 's'}, ` +
|
|
77
|
+
`${counts.knowledge} knowledge entr${counts.knowledge === 1 ? 'y' : 'ies'}.`);
|
|
78
|
+
if (counts.rules === 0 &&
|
|
79
|
+
counts.boundaries === 0 &&
|
|
80
|
+
counts.paths === 0 &&
|
|
81
|
+
counts.knowledge === 0) {
|
|
82
|
+
lines.push('No registry entries matched. The file may be outside the conventions, or the workspace may not have rules / paths defined yet.');
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
lines.push('See `data` for the full per-category list.');
|
|
86
|
+
}
|
|
87
|
+
return lines.join('\n');
|
|
88
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-api-surface-diff.tool.d.ts","sourceRoot":"","sources":["../../src/tools/get-api-surface-diff.tool.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAUpE,eAAO,MAAM,qBAAqB,EAAE,eAsDnC,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import * as nodePath from 'node:path';
|
|
3
|
+
import { diffApiSurfaces, extractApiSurface, } from '@shrkcrft/api-surface-diff';
|
|
4
|
+
import { GraphStore } from '@shrkcrft/graph';
|
|
5
|
+
const NEXT = 'shrk graph index';
|
|
6
|
+
export const getApiSurfaceDiffTool = {
|
|
7
|
+
name: 'get_api_surface_diff',
|
|
8
|
+
description: 'Read-only: compare the current code-graph public-API surface to a baseline. Provide `baselinePath` (file system path to a previously captured `IApiSurface`) OR `baseline` (inline). Optional `packages` filter restricts both sides to those workspace packages.',
|
|
9
|
+
cliCommand: 'api-diff',
|
|
10
|
+
inputSchema: {
|
|
11
|
+
type: 'object',
|
|
12
|
+
properties: {
|
|
13
|
+
baselinePath: { type: 'string' },
|
|
14
|
+
baseline: { type: 'object' },
|
|
15
|
+
packages: { type: 'array', items: { type: 'string' } },
|
|
16
|
+
},
|
|
17
|
+
additionalProperties: false,
|
|
18
|
+
},
|
|
19
|
+
handler(input, ctx) {
|
|
20
|
+
const args = input;
|
|
21
|
+
const store = new GraphStore(ctx.inspection.projectRoot);
|
|
22
|
+
if (!store.exists()) {
|
|
23
|
+
return {
|
|
24
|
+
isError: true,
|
|
25
|
+
error: {
|
|
26
|
+
code: 'graph-missing',
|
|
27
|
+
message: "code-graph store missing",
|
|
28
|
+
details: { nextCommand: NEXT },
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
let baseline = args.baseline;
|
|
33
|
+
if (!baseline && args.baselinePath) {
|
|
34
|
+
const abs = nodePath.isAbsolute(args.baselinePath)
|
|
35
|
+
? args.baselinePath
|
|
36
|
+
: nodePath.resolve(ctx.inspection.projectRoot, args.baselinePath);
|
|
37
|
+
try {
|
|
38
|
+
baseline = JSON.parse(readFileSync(abs, 'utf8'));
|
|
39
|
+
}
|
|
40
|
+
catch (e) {
|
|
41
|
+
return {
|
|
42
|
+
isError: true,
|
|
43
|
+
error: { code: 'invalid-input', message: `baseline read failed: ${e.message}` },
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (!baseline) {
|
|
48
|
+
return {
|
|
49
|
+
isError: true,
|
|
50
|
+
error: { code: 'invalid-input', message: 'baseline or baselinePath is required' },
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
const snap = store.loadSnapshot();
|
|
54
|
+
const current = extractApiSurface(snap, {
|
|
55
|
+
...(args.packages && args.packages.length > 0 ? { packageFilter: args.packages } : {}),
|
|
56
|
+
});
|
|
57
|
+
const diff = diffApiSurfaces(baseline, current);
|
|
58
|
+
return { data: diff };
|
|
59
|
+
},
|
|
60
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-arch-violations.tool.d.ts","sourceRoot":"","sources":["../../src/tools/get-arch-violations.tool.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAWpE,eAAO,MAAM,qBAAqB,EAAE,eA6BnC,CAAC"}
|