ast-mcp-server 0.11.2 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -2
- package/README.md +60 -10
- package/SECURITY.md +1 -1
- package/cordis.patch.yml +31 -0
- package/dist/batch/schema.js +7 -16
- package/dist/server.js +7 -32
- package/dist/services/agent-setup.js +85 -19
- package/dist/services/agent-targets.js +170 -80
- package/dist/services/diagnostics.js +55 -0
- package/dist/services/opencode-config.js +84 -7
- package/dist/services/runtime-policy.js +15 -0
- package/dist/tools/apply_operation.js +5 -2
- package/dist/tools/catalog.js +83 -0
- package/dist/tools/explore.js +5 -2
- package/dist/tools/find_references.js +5 -2
- package/dist/tools/find_test_candidates.js +5 -2
- package/dist/tools/get_diagnostics.js +36 -4
- package/dist/tools/get_file.js +5 -2
- package/dist/tools/get_impact.js +5 -2
- package/dist/tools/get_operation_preview.js +5 -2
- package/dist/tools/get_outline.js +5 -2
- package/dist/tools/get_project_status.js +5 -2
- package/dist/tools/get_symbol_source.js +5 -2
- package/dist/tools/list_files.js +5 -2
- package/dist/tools/rename_symbol.js +5 -2
- package/dist/tools/replace_symbol_body.js +5 -2
- package/dist/tools/scaffold_class.js +5 -2
- package/dist/tools/search_symbols.js +5 -2
- package/dist/worker-runtime.js +2 -2
- package/docs/support.md +7 -7
- package/package.json +16 -3
- package/skills/structural-code-editing/SKILL.md +14 -2
- package/skills/structural-code-editing/releases.json +22 -2
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { toolDescriptor as applyOperation } from "./apply_operation.js";
|
|
2
|
+
import { toolDescriptor as explore } from "./explore.js";
|
|
3
|
+
import { toolDescriptor as findReferences } from "./find_references.js";
|
|
4
|
+
import { toolDescriptor as findTestCandidates } from "./find_test_candidates.js";
|
|
5
|
+
import { toolDescriptor as getDiagnostics } from "./get_diagnostics.js";
|
|
6
|
+
import { toolDescriptor as getFile } from "./get_file.js";
|
|
7
|
+
import { toolDescriptor as getImpact } from "./get_impact.js";
|
|
8
|
+
import { toolDescriptor as getOperationPreview } from "./get_operation_preview.js";
|
|
9
|
+
import { toolDescriptor as getOutline } from "./get_outline.js";
|
|
10
|
+
import { toolDescriptor as getProjectStatus } from "./get_project_status.js";
|
|
11
|
+
import { toolDescriptor as getSymbolSource } from "./get_symbol_source.js";
|
|
12
|
+
import { toolDescriptor as listFiles } from "./list_files.js";
|
|
13
|
+
import { toolDescriptor as renameSymbol } from "./rename_symbol.js";
|
|
14
|
+
import { toolDescriptor as replaceSymbolBody } from "./replace_symbol_body.js";
|
|
15
|
+
import { toolDescriptor as scaffoldClass } from "./scaffold_class.js";
|
|
16
|
+
import { toolDescriptor as searchSymbols } from "./search_symbols.js";
|
|
17
|
+
function validateDescriptor(descriptor) {
|
|
18
|
+
const formats = descriptor.directOutputFormats.join(",");
|
|
19
|
+
const valid = (descriptor.effect === "read" &&
|
|
20
|
+
(descriptor.batch === "none" || descriptor.batch === "read") &&
|
|
21
|
+
(formats === "json" || formats === "json,toon")) ||
|
|
22
|
+
(descriptor.effect === "prepare" && descriptor.batch === "prepare" && formats === "json") ||
|
|
23
|
+
(descriptor.effect === "apply" && descriptor.batch === "none" && formats === "json");
|
|
24
|
+
if (!valid)
|
|
25
|
+
throw new Error(`Contradictory capability descriptor: ${descriptor.name}`);
|
|
26
|
+
}
|
|
27
|
+
export function defineToolCatalog(input) {
|
|
28
|
+
const seen = new Set();
|
|
29
|
+
for (const descriptor of input) {
|
|
30
|
+
if (seen.has(descriptor.name))
|
|
31
|
+
throw new Error(`Duplicate tool name: ${descriptor.name}`);
|
|
32
|
+
seen.add(descriptor.name);
|
|
33
|
+
validateDescriptor(descriptor);
|
|
34
|
+
}
|
|
35
|
+
const descriptors = Object.freeze(input.map((descriptor) => Object.freeze({
|
|
36
|
+
...descriptor,
|
|
37
|
+
directOutputFormats: Object.freeze([...descriptor.directOutputFormats]),
|
|
38
|
+
})));
|
|
39
|
+
const names = (predicate) => Object.freeze(descriptors.filter(predicate).map(({ name }) => name));
|
|
40
|
+
return Object.freeze({
|
|
41
|
+
descriptors,
|
|
42
|
+
batch: Object.freeze({
|
|
43
|
+
read: names((item) => item.batch === "read"),
|
|
44
|
+
prepare: names((item) => item.batch === "prepare"),
|
|
45
|
+
excluded: names((item) => item.batch === "none"),
|
|
46
|
+
}),
|
|
47
|
+
compatibility: Object.freeze({
|
|
48
|
+
required: names((item) => item.compatibility === "required"),
|
|
49
|
+
optional: names((item) => item.compatibility === "optional"),
|
|
50
|
+
}),
|
|
51
|
+
byEffect: Object.freeze({
|
|
52
|
+
read: names((item) => item.effect === "read"),
|
|
53
|
+
prepare: names((item) => item.effect === "prepare"),
|
|
54
|
+
apply: names((item) => item.effect === "apply"),
|
|
55
|
+
}),
|
|
56
|
+
directToon: names((item) => item.directOutputFormats.length === 2),
|
|
57
|
+
registerAll(server, options = {}) {
|
|
58
|
+
for (const descriptor of descriptors) {
|
|
59
|
+
if (options.denyApply === true && descriptor.effect === "apply")
|
|
60
|
+
continue;
|
|
61
|
+
descriptor.register(server);
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
export const toolCatalog = defineToolCatalog([
|
|
67
|
+
listFiles,
|
|
68
|
+
getProjectStatus,
|
|
69
|
+
explore,
|
|
70
|
+
getOutline,
|
|
71
|
+
getSymbolSource,
|
|
72
|
+
searchSymbols,
|
|
73
|
+
findReferences,
|
|
74
|
+
getImpact,
|
|
75
|
+
findTestCandidates,
|
|
76
|
+
getDiagnostics,
|
|
77
|
+
getFile,
|
|
78
|
+
renameSymbol,
|
|
79
|
+
replaceSymbolBody,
|
|
80
|
+
scaffoldClass,
|
|
81
|
+
getOperationPreview,
|
|
82
|
+
applyOperation,
|
|
83
|
+
]);
|
package/dist/tools/explore.js
CHANGED
|
@@ -8,6 +8,7 @@ import { createRequestContext } from "../services/request-context.js";
|
|
|
8
8
|
import { FRESHNESS_CAUSES, SNAPSHOT_STATES, TRUNCATION_REASONS, } from "../services/read-contracts.js";
|
|
9
9
|
import { createToolErrorContext, errorResult, structuredResult } from "./result.js";
|
|
10
10
|
import { RelationshipEndpointSchema } from "./relationship-schema.js";
|
|
11
|
+
const TOOL_NAME = "ast_explore";
|
|
11
12
|
const ExploreDetailSchema = z.enum(["selectors", "summary", "context", "full"]).default("summary");
|
|
12
13
|
const ReferenceDetailSchema = z.enum(["locations", "context"]).default("locations");
|
|
13
14
|
const CallSpinesInputSchema = z.object({
|
|
@@ -200,7 +201,7 @@ const ExploreOutputSchema = z.object({
|
|
|
200
201
|
}),
|
|
201
202
|
});
|
|
202
203
|
export function registerExplore(server) {
|
|
203
|
-
server.registerTool(
|
|
204
|
+
server.registerTool(TOOL_NAME, {
|
|
204
205
|
title: "Explore project context",
|
|
205
206
|
description: "Composes bounded structural search, exact selectors, source evidence and compiler references without weakening the primitive AST tools. Returns bounded session freshness metadata for fresh, pending, stale, rebuilding or degraded state.",
|
|
206
207
|
inputSchema: ExploreInputSchema,
|
|
@@ -241,7 +242,9 @@ export function registerExplore(server) {
|
|
|
241
242
|
return structuredResult(ExploreOutputSchema.parse(output));
|
|
242
243
|
}
|
|
243
244
|
catch (error) {
|
|
244
|
-
return errorResult(error, createToolErrorContext(
|
|
245
|
+
return errorResult(error, createToolErrorContext(TOOL_NAME, project_root));
|
|
245
246
|
}
|
|
246
247
|
});
|
|
247
248
|
}
|
|
249
|
+
// prettier-ignore
|
|
250
|
+
export const toolDescriptor = Object.freeze({ name: TOOL_NAME, register: registerExplore, compatibility: "optional", effect: "read", batch: "read", directOutputFormats: Object.freeze(["json"]) });
|
|
@@ -4,6 +4,7 @@ import { findDeclarationByName, getSourceFileOrThrow, withProject } from "../ser
|
|
|
4
4
|
import { collectSymbolReferences } from "../services/references.js";
|
|
5
5
|
import { createRequestContext } from "../services/request-context.js";
|
|
6
6
|
import { createToolErrorContext, errorResult, formattedResult, ToolOutputFormatInputSchema, } from "./result.js";
|
|
7
|
+
const TOOL_NAME = "ast_find_references";
|
|
7
8
|
const ReferenceDetailSchema = z.enum(["locations", "context"]).default("locations");
|
|
8
9
|
const AstFindReferencesInputSchema = z.object({
|
|
9
10
|
project_root: z
|
|
@@ -44,7 +45,7 @@ const ReferenceOutputSchemas = {
|
|
|
44
45
|
}),
|
|
45
46
|
};
|
|
46
47
|
export function registerFindReferences(server) {
|
|
47
|
-
server.registerTool(
|
|
48
|
+
server.registerTool(TOOL_NAME, {
|
|
48
49
|
title: "Find semantic symbol references",
|
|
49
50
|
description: "Finds type-resolved references and returns bounded project-relative locations, including declaration impact by default.",
|
|
50
51
|
inputSchema: AstFindReferencesInputSchema,
|
|
@@ -76,7 +77,9 @@ export function registerFindReferences(server) {
|
|
|
76
77
|
return formattedResult(outputSchema, structuredContent, output_format);
|
|
77
78
|
}
|
|
78
79
|
catch (error) {
|
|
79
|
-
return errorResult(error, createToolErrorContext(
|
|
80
|
+
return errorResult(error, createToolErrorContext(TOOL_NAME, project_root));
|
|
80
81
|
}
|
|
81
82
|
});
|
|
82
83
|
}
|
|
84
|
+
// prettier-ignore
|
|
85
|
+
export const toolDescriptor = Object.freeze({ name: TOOL_NAME, register: registerFindReferences, compatibility: "required", effect: "read", batch: "read", directOutputFormats: Object.freeze(["json", "toon"]) });
|
|
@@ -7,6 +7,7 @@ import { createRequestContext } from "../services/request-context.js";
|
|
|
7
7
|
import { findTestCandidates, MAX_TEST_CANDIDATE_CONVENTION_ITEMS, MAX_TEST_CANDIDATE_CONVENTION_LENGTH, TEST_CANDIDATE_CONFIDENCES, TEST_CANDIDATE_REASONS, } from "../services/test-candidates.js";
|
|
8
8
|
import { FreshnessSchema, RelationshipEdgeSchema, RelationshipEndpointSchema, } from "./relationship-schema.js";
|
|
9
9
|
import { createToolErrorContext, errorResult, structuredResult } from "./result.js";
|
|
10
|
+
const TOOL_NAME = "ast_find_test_candidates";
|
|
10
11
|
const ConventionSchema = z
|
|
11
12
|
.array(z.string().min(1).max(MAX_TEST_CANDIDATE_CONVENTION_LENGTH))
|
|
12
13
|
.max(MAX_TEST_CANDIDATE_CONVENTION_ITEMS)
|
|
@@ -59,7 +60,7 @@ const FindTestCandidatesOutputSchema = z.object({
|
|
|
59
60
|
}),
|
|
60
61
|
});
|
|
61
62
|
export function registerFindTestCandidates(server) {
|
|
62
|
-
server.registerTool(
|
|
63
|
+
server.registerTool(TOOL_NAME, {
|
|
63
64
|
title: "Find compiler-backed affected test candidates",
|
|
64
65
|
description: "Finds deterministic affected test candidates from fresh, complete incoming compiler relationships. Returns bounded whole-candidate proofs and never executes tests or prepares mutations.",
|
|
65
66
|
inputSchema: AstFindTestCandidatesInputSchema,
|
|
@@ -118,7 +119,9 @@ export function registerFindTestCandidates(server) {
|
|
|
118
119
|
return structuredResult(FindTestCandidatesOutputSchema.parse(result));
|
|
119
120
|
}
|
|
120
121
|
catch (error) {
|
|
121
|
-
return errorResult(error, createToolErrorContext(
|
|
122
|
+
return errorResult(error, createToolErrorContext(TOOL_NAME, project_root));
|
|
122
123
|
}
|
|
123
124
|
});
|
|
124
125
|
}
|
|
126
|
+
// prettier-ignore
|
|
127
|
+
export const toolDescriptor = Object.freeze({ name: TOOL_NAME, register: registerFindTestCandidates, compatibility: "required", effect: "read", batch: "read", directOutputFormats: Object.freeze(["json"]) });
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { normalizeDiagnostic } from "../services/diagnostics.js";
|
|
2
|
+
import { buildDiagnosticAggregates, DIAGNOSTIC_AGGREGATE_GROUP_LIMIT, normalizeDiagnostic, } from "../services/diagnostics.js";
|
|
3
3
|
import { PaginationInputSchema, PaginationOutputSchema, paginate } from "../services/pagination.js";
|
|
4
4
|
import { getSourceFileOrThrow, withProject } from "../services/project.js";
|
|
5
5
|
import { createRequestContext } from "../services/request-context.js";
|
|
6
6
|
import { createToolErrorContext, errorResult, formattedResult, ToolOutputFormatInputSchema, } from "./result.js";
|
|
7
|
+
const TOOL_NAME = "ast_get_diagnostics";
|
|
7
8
|
const DiagnosticSchema = z.object({
|
|
8
9
|
code: z.number().int(),
|
|
9
10
|
category: z.string(),
|
|
@@ -12,6 +13,29 @@ const DiagnosticSchema = z.object({
|
|
|
12
13
|
column: z.number().int().positive().nullable(),
|
|
13
14
|
message: z.string(),
|
|
14
15
|
});
|
|
16
|
+
const AggregateMetadataSchema = {
|
|
17
|
+
total_group_count: z.number().int().safe().min(0),
|
|
18
|
+
omitted_group_count: z.number().int().safe().min(0),
|
|
19
|
+
covered_diagnostic_count: z.number().int().safe().min(0),
|
|
20
|
+
omitted_diagnostic_count: z.number().int().safe().min(0),
|
|
21
|
+
truncated: z.boolean(),
|
|
22
|
+
};
|
|
23
|
+
const DiagnosticAggregatesSchema = z.object({
|
|
24
|
+
group_limit: z.literal(DIAGNOSTIC_AGGREGATE_GROUP_LIMIT),
|
|
25
|
+
codes: z.object({
|
|
26
|
+
groups: z
|
|
27
|
+
.array(z.object({ code: z.number().int().safe(), count: z.number().int().safe().positive() }))
|
|
28
|
+
.max(DIAGNOSTIC_AGGREGATE_GROUP_LIMIT),
|
|
29
|
+
...AggregateMetadataSchema,
|
|
30
|
+
}),
|
|
31
|
+
files: z.object({
|
|
32
|
+
groups: z
|
|
33
|
+
.array(z.object({ file: z.string(), count: z.number().int().safe().positive() }))
|
|
34
|
+
.max(DIAGNOSTIC_AGGREGATE_GROUP_LIMIT),
|
|
35
|
+
...AggregateMetadataSchema,
|
|
36
|
+
unfiled_diagnostic_count: z.number().int().safe().min(0),
|
|
37
|
+
}),
|
|
38
|
+
});
|
|
15
39
|
const AstGetDiagnosticsInputSchema = z.object({
|
|
16
40
|
project_root: z
|
|
17
41
|
.string()
|
|
@@ -20,6 +44,7 @@ const AstGetDiagnosticsInputSchema = z.object({
|
|
|
20
44
|
.string()
|
|
21
45
|
.optional()
|
|
22
46
|
.describe("Optional project-relative or absolute file path. Omit for project diagnostics."),
|
|
47
|
+
include_aggregates: z.boolean().optional().default(false),
|
|
23
48
|
...ToolOutputFormatInputSchema,
|
|
24
49
|
...PaginationInputSchema,
|
|
25
50
|
});
|
|
@@ -28,10 +53,11 @@ const AstGetDiagnosticsOutputSchema = z.object({
|
|
|
28
53
|
error_count: z.number().int().min(0),
|
|
29
54
|
warning_count: z.number().int().min(0),
|
|
30
55
|
duration_ms: z.number().min(0),
|
|
56
|
+
aggregates: DiagnosticAggregatesSchema.optional(),
|
|
31
57
|
...PaginationOutputSchema,
|
|
32
58
|
});
|
|
33
59
|
export function registerGetDiagnostics(server) {
|
|
34
|
-
server.registerTool(
|
|
60
|
+
server.registerTool(TOOL_NAME, {
|
|
35
61
|
title: "Get TypeScript diagnostics",
|
|
36
62
|
description: "Returns bounded normalized TypeScript diagnostics for a project or one source file. Existing errors are preserved as evidence for write-operation delta checks.",
|
|
37
63
|
inputSchema: AstGetDiagnosticsInputSchema,
|
|
@@ -41,7 +67,7 @@ export function registerGetDiagnostics(server) {
|
|
|
41
67
|
idempotentHint: true,
|
|
42
68
|
openWorldHint: false,
|
|
43
69
|
},
|
|
44
|
-
}, async ({ project_root, file_path, output_format, offset, limit }, extra) => {
|
|
70
|
+
}, async ({ project_root, file_path, include_aggregates, output_format, offset, limit }, extra) => {
|
|
45
71
|
const requestContext = createRequestContext(extra.signal);
|
|
46
72
|
try {
|
|
47
73
|
const structuredContent = await withProject(project_root, ({ project, projectRoot }, operationContext) => {
|
|
@@ -52,6 +78,9 @@ export function registerGetDiagnostics(server) {
|
|
|
52
78
|
const normalized = diagnostics
|
|
53
79
|
.map((diagnostic) => normalizeDiagnostic(diagnostic, projectRoot, operationContext))
|
|
54
80
|
.sort((left, right) => `${left.file ?? ""}:${left.line ?? 0}:${left.column ?? 0}:${left.code}`.localeCompare(`${right.file ?? ""}:${right.line ?? 0}:${right.column ?? 0}:${right.code}`));
|
|
81
|
+
const aggregates = include_aggregates
|
|
82
|
+
? buildDiagnosticAggregates(normalized, operationContext)
|
|
83
|
+
: undefined;
|
|
55
84
|
const page = paginate(normalized, offset, limit);
|
|
56
85
|
const { items, ...metadata } = page;
|
|
57
86
|
return {
|
|
@@ -61,13 +90,16 @@ export function registerGetDiagnostics(server) {
|
|
|
61
90
|
warning_count: normalized.filter((diagnostic) => diagnostic.category === "Warning")
|
|
62
91
|
.length,
|
|
63
92
|
duration_ms: performance.now() - startedAt,
|
|
93
|
+
...(aggregates ? { aggregates } : {}),
|
|
64
94
|
...metadata,
|
|
65
95
|
};
|
|
66
96
|
}, requestContext);
|
|
67
97
|
return formattedResult(AstGetDiagnosticsOutputSchema, structuredContent, output_format);
|
|
68
98
|
}
|
|
69
99
|
catch (error) {
|
|
70
|
-
return errorResult(error, createToolErrorContext(
|
|
100
|
+
return errorResult(error, createToolErrorContext(TOOL_NAME, project_root));
|
|
71
101
|
}
|
|
72
102
|
});
|
|
73
103
|
}
|
|
104
|
+
// prettier-ignore
|
|
105
|
+
export const toolDescriptor = Object.freeze({ name: TOOL_NAME, register: registerGetDiagnostics, compatibility: "required", effect: "read", batch: "read", directOutputFormats: Object.freeze(["json", "toon"]) });
|
package/dist/tools/get_file.js
CHANGED
|
@@ -5,6 +5,7 @@ import { getSourceFileOrThrow, withProject } from "../services/project.js";
|
|
|
5
5
|
import { createRequestContext } from "../services/request-context.js";
|
|
6
6
|
import { FRESHNESS_CAUSES, SNAPSHOT_STATES } from "../services/read-contracts.js";
|
|
7
7
|
import { createToolErrorContext, errorResult, structuredResult } from "./result.js";
|
|
8
|
+
const TOOL_NAME = "ast_get_file";
|
|
8
9
|
const AstGetFileInputSchema = z.object({
|
|
9
10
|
project_root: z
|
|
10
11
|
.string()
|
|
@@ -60,7 +61,7 @@ const AstGetFileOutputSchema = z.object({
|
|
|
60
61
|
symbols: z.array(OutlineSymbolSchema).optional(),
|
|
61
62
|
});
|
|
62
63
|
export function registerGetFile(server) {
|
|
63
|
-
server.registerTool(
|
|
64
|
+
server.registerTool(TOOL_NAME, {
|
|
64
65
|
title: "Get bounded source file",
|
|
65
66
|
description: "Returns exact bounded source lines for one TypeScript/JavaScript file, or body-free symbols when symbols_only is true. Read-only; file snapshot freshness and project freshness are reported separately from compiler diagnostics.",
|
|
66
67
|
inputSchema: AstGetFileInputSchema,
|
|
@@ -101,7 +102,9 @@ export function registerGetFile(server) {
|
|
|
101
102
|
return structuredResult(structuredContent);
|
|
102
103
|
}
|
|
103
104
|
catch (error) {
|
|
104
|
-
return errorResult(error, createToolErrorContext(
|
|
105
|
+
return errorResult(error, createToolErrorContext(TOOL_NAME, project_root));
|
|
105
106
|
}
|
|
106
107
|
});
|
|
107
108
|
}
|
|
109
|
+
// prettier-ignore
|
|
110
|
+
export const toolDescriptor = Object.freeze({ name: TOOL_NAME, register: registerGetFile, compatibility: "optional", effect: "read", batch: "none", directOutputFormats: Object.freeze(["json"]) });
|
package/dist/tools/get_impact.js
CHANGED
|
@@ -6,6 +6,7 @@ import { createRequestContext } from "../services/request-context.js";
|
|
|
6
6
|
import { RELATIONSHIP_EDGE_KINDS } from "../services/relationships.js";
|
|
7
7
|
import { FreshnessSchema, RelationshipEdgeSchema, RelationshipEndpointSchema, } from "./relationship-schema.js";
|
|
8
8
|
import { createToolErrorContext, errorResult, formattedResult, ToolOutputFormatInputSchema, } from "./result.js";
|
|
9
|
+
const TOOL_NAME = "ast_get_impact";
|
|
9
10
|
const AstGetImpactInputSchema = z.object({
|
|
10
11
|
project_root: z
|
|
11
12
|
.string()
|
|
@@ -68,7 +69,7 @@ const ImpactOutputSchema = z.object({
|
|
|
68
69
|
freshness: FreshnessSchema,
|
|
69
70
|
});
|
|
70
71
|
export function registerGetImpact(server) {
|
|
71
|
-
server.registerTool(
|
|
72
|
+
server.registerTool(TOOL_NAME, {
|
|
72
73
|
title: "Get bounded compiler-backed impact",
|
|
73
74
|
description: "Traverses exact compiler-backed relationships around a symbol with explicit direction, depth, node and edge budgets. Returns bounded session freshness metadata and fails closed when exact relationships are not fresh. Read-only evidence only; it never prepares or applies mutations.",
|
|
74
75
|
inputSchema: AstGetImpactInputSchema,
|
|
@@ -101,7 +102,9 @@ export function registerGetImpact(server) {
|
|
|
101
102
|
return formattedResult(ImpactOutputSchema, structuredContent, output_format);
|
|
102
103
|
}
|
|
103
104
|
catch (error) {
|
|
104
|
-
return errorResult(error, createToolErrorContext(
|
|
105
|
+
return errorResult(error, createToolErrorContext(TOOL_NAME, project_root));
|
|
105
106
|
}
|
|
106
107
|
});
|
|
107
108
|
}
|
|
109
|
+
// prettier-ignore
|
|
110
|
+
export const toolDescriptor = Object.freeze({ name: TOOL_NAME, register: registerGetImpact, compatibility: "optional", effect: "read", batch: "none", directOutputFormats: Object.freeze(["json", "toon"]) });
|
|
@@ -2,6 +2,7 @@ import { z } from "zod";
|
|
|
2
2
|
import { getOperationPreview } from "../services/operations.js";
|
|
3
3
|
import { createRequestContext } from "../services/request-context.js";
|
|
4
4
|
import { createToolErrorContext, errorResult, structuredResult } from "./result.js";
|
|
5
|
+
const TOOL_NAME = "ast_get_operation_preview";
|
|
5
6
|
const AstGetOperationPreviewInputSchema = z.object({
|
|
6
7
|
operation_id: z.string().uuid(),
|
|
7
8
|
file: z.string().optional().describe("Optional affected file path to retrieve only its diff."),
|
|
@@ -12,7 +13,7 @@ const AstGetOperationPreviewOutputSchema = z.object({
|
|
|
12
13
|
files: z.array(z.object({ file: z.string(), diff: z.string() })),
|
|
13
14
|
});
|
|
14
15
|
export function registerGetOperationPreview(server) {
|
|
15
|
-
server.registerTool(
|
|
16
|
+
server.registerTool(TOOL_NAME, {
|
|
16
17
|
title: "Get complete prepared-operation diff",
|
|
17
18
|
description: "Retrieves exact unified diffs retained for a prepared operation, optionally one affected file at a time.",
|
|
18
19
|
inputSchema: AstGetOperationPreviewInputSchema,
|
|
@@ -30,7 +31,9 @@ export function registerGetOperationPreview(server) {
|
|
|
30
31
|
return structuredResult(output);
|
|
31
32
|
}
|
|
32
33
|
catch (error) {
|
|
33
|
-
return errorResult(error, createToolErrorContext(
|
|
34
|
+
return errorResult(error, createToolErrorContext(TOOL_NAME));
|
|
34
35
|
}
|
|
35
36
|
});
|
|
36
37
|
}
|
|
38
|
+
// prettier-ignore
|
|
39
|
+
export const toolDescriptor = Object.freeze({ name: TOOL_NAME, register: registerGetOperationPreview, compatibility: "required", effect: "read", batch: "none", directOutputFormats: Object.freeze(["json"]) });
|
|
@@ -4,6 +4,7 @@ import { buildFileOutline } from "../services/outline.js";
|
|
|
4
4
|
import { getSourceFileOrThrow, withProject } from "../services/project.js";
|
|
5
5
|
import { createRequestContext } from "../services/request-context.js";
|
|
6
6
|
import { createToolErrorContext, errorResult, structuredResult } from "./result.js";
|
|
7
|
+
const TOOL_NAME = "ast_get_outline";
|
|
7
8
|
const AstGetOutlineInputSchema = z.object({
|
|
8
9
|
project_root: z
|
|
9
10
|
.string()
|
|
@@ -28,7 +29,7 @@ const AstGetOutlineOutputSchema = z.object({
|
|
|
28
29
|
symbols: z.array(OutlineSymbolSchema).optional(),
|
|
29
30
|
});
|
|
30
31
|
export function registerGetOutline(server) {
|
|
31
|
-
server.registerTool(
|
|
32
|
+
server.registerTool(TOOL_NAME, {
|
|
32
33
|
title: "Get compact file outline",
|
|
33
34
|
description: "Returns body-free declaration signatures for one TypeScript/JavaScript file. Detailed symbol metadata is opt-in because it duplicates signature text.",
|
|
34
35
|
inputSchema: AstGetOutlineInputSchema,
|
|
@@ -54,7 +55,9 @@ export function registerGetOutline(server) {
|
|
|
54
55
|
return structuredResult(structuredContent);
|
|
55
56
|
}
|
|
56
57
|
catch (error) {
|
|
57
|
-
return errorResult(error, createToolErrorContext(
|
|
58
|
+
return errorResult(error, createToolErrorContext(TOOL_NAME, project_root));
|
|
58
59
|
}
|
|
59
60
|
});
|
|
60
61
|
}
|
|
62
|
+
// prettier-ignore
|
|
63
|
+
export const toolDescriptor = Object.freeze({ name: TOOL_NAME, register: registerGetOutline, compatibility: "required", effect: "read", batch: "read", directOutputFormats: Object.freeze(["json"]) });
|
|
@@ -3,6 +3,7 @@ import { FRESHNESS_CAUSES, SNAPSHOT_STATES, TRUNCATION_REASONS, } from "../servi
|
|
|
3
3
|
import { getProjectStatus } from "../services/project.js";
|
|
4
4
|
import { createRequestContext } from "../services/request-context.js";
|
|
5
5
|
import { createToolErrorContext, errorResult, structuredResult } from "./result.js";
|
|
6
|
+
const TOOL_NAME = "ast_get_project_status";
|
|
6
7
|
const AstGetProjectStatusInputSchema = z.object({
|
|
7
8
|
project_root: z
|
|
8
9
|
.string()
|
|
@@ -113,7 +114,7 @@ const ProjectStatusOutputSchema = z.object({
|
|
|
113
114
|
index_observability: IndexObservabilitySchema,
|
|
114
115
|
});
|
|
115
116
|
export function registerGetProjectStatus(server) {
|
|
116
|
-
server.registerTool(
|
|
117
|
+
server.registerTool(TOOL_NAME, {
|
|
117
118
|
title: "Get project freshness status",
|
|
118
119
|
description: "Returns bounded, read-only compiler freshness and project status without exposing filesystem identities or credentials.",
|
|
119
120
|
inputSchema: AstGetProjectStatusInputSchema,
|
|
@@ -131,7 +132,9 @@ export function registerGetProjectStatus(server) {
|
|
|
131
132
|
return structuredResult({ ...output });
|
|
132
133
|
}
|
|
133
134
|
catch (error) {
|
|
134
|
-
return errorResult(error, createToolErrorContext(
|
|
135
|
+
return errorResult(error, createToolErrorContext(TOOL_NAME, project_root));
|
|
135
136
|
}
|
|
136
137
|
});
|
|
137
138
|
}
|
|
139
|
+
// prettier-ignore
|
|
140
|
+
export const toolDescriptor = Object.freeze({ name: TOOL_NAME, register: registerGetProjectStatus, compatibility: "optional", effect: "read", batch: "none", directOutputFormats: Object.freeze(["json"]) });
|
|
@@ -3,6 +3,7 @@ import { nodeSourceWithLocation } from "../services/outline.js";
|
|
|
3
3
|
import { findDeclarationByName, getSourceFileOrThrow, withProject } from "../services/project.js";
|
|
4
4
|
import { createRequestContext } from "../services/request-context.js";
|
|
5
5
|
import { createToolErrorContext, errorResult, structuredResult } from "./result.js";
|
|
6
|
+
const TOOL_NAME = "ast_get_symbol_source";
|
|
6
7
|
const AstGetSymbolSourceInputSchema = z.object({
|
|
7
8
|
project_root: z
|
|
8
9
|
.string()
|
|
@@ -17,7 +18,7 @@ const AstGetSymbolSourceOutputSchema = z.object({
|
|
|
17
18
|
text: z.string(),
|
|
18
19
|
});
|
|
19
20
|
export function registerGetSymbolSource(server) {
|
|
20
|
-
server.registerTool(
|
|
21
|
+
server.registerTool(TOOL_NAME, {
|
|
21
22
|
title: "Get one symbol implementation",
|
|
22
23
|
description: "Returns exactly one declaration or implementation with its project-relative location, not the complete file.",
|
|
23
24
|
inputSchema: AstGetSymbolSourceInputSchema,
|
|
@@ -39,7 +40,9 @@ export function registerGetSymbolSource(server) {
|
|
|
39
40
|
return structuredResult(structuredContent);
|
|
40
41
|
}
|
|
41
42
|
catch (error) {
|
|
42
|
-
return errorResult(error, createToolErrorContext(
|
|
43
|
+
return errorResult(error, createToolErrorContext(TOOL_NAME, project_root));
|
|
43
44
|
}
|
|
44
45
|
});
|
|
45
46
|
}
|
|
47
|
+
// prettier-ignore
|
|
48
|
+
export const toolDescriptor = Object.freeze({ name: TOOL_NAME, register: registerGetSymbolSource, compatibility: "required", effect: "read", batch: "read", directOutputFormats: Object.freeze(["json"]) });
|
package/dist/tools/list_files.js
CHANGED
|
@@ -4,6 +4,7 @@ import { PaginationInputSchema, PaginationOutputSchema, paginate } from "../serv
|
|
|
4
4
|
import { withProject } from "../services/project.js";
|
|
5
5
|
import { createRequestContext } from "../services/request-context.js";
|
|
6
6
|
import { createToolErrorContext, errorResult, structuredResult } from "./result.js";
|
|
7
|
+
const TOOL_NAME = "ast_list_files";
|
|
7
8
|
const AstListFilesInputSchema = z.object({
|
|
8
9
|
project_root: z
|
|
9
10
|
.string()
|
|
@@ -19,7 +20,7 @@ const AstListFilesOutputSchema = z.object({
|
|
|
19
20
|
...PaginationOutputSchema,
|
|
20
21
|
});
|
|
21
22
|
export function registerListFiles(server) {
|
|
22
|
-
server.registerTool(
|
|
23
|
+
server.registerTool(TOOL_NAME, {
|
|
23
24
|
title: "List TypeScript/JavaScript project files",
|
|
24
25
|
description: "Lists source files included by the project's tsconfig in deterministic, project-relative, paginated form.",
|
|
25
26
|
inputSchema: AstListFilesInputSchema,
|
|
@@ -50,7 +51,9 @@ export function registerListFiles(server) {
|
|
|
50
51
|
return structuredResult(output);
|
|
51
52
|
}
|
|
52
53
|
catch (error) {
|
|
53
|
-
return errorResult(error, createToolErrorContext(
|
|
54
|
+
return errorResult(error, createToolErrorContext(TOOL_NAME, project_root));
|
|
54
55
|
}
|
|
55
56
|
});
|
|
56
57
|
}
|
|
58
|
+
// prettier-ignore
|
|
59
|
+
export const toolDescriptor = Object.freeze({ name: TOOL_NAME, register: registerListFiles, compatibility: "required", effect: "read", batch: "read", directOutputFormats: Object.freeze(["json"]) });
|
|
@@ -3,6 +3,7 @@ import { prepareRename } from "../services/operations.js";
|
|
|
3
3
|
import { createRequestContext } from "../services/request-context.js";
|
|
4
4
|
import { PreparedOperationOutputSchema, serializePreparedOperation } from "./operation-schema.js";
|
|
5
5
|
import { createToolErrorContext, errorResult, structuredResult } from "./result.js";
|
|
6
|
+
const TOOL_NAME = "ast_rename_symbol";
|
|
6
7
|
const AstRenameSymbolInputSchema = z.object({
|
|
7
8
|
project_root: z.string(),
|
|
8
9
|
file_path: z.string(),
|
|
@@ -18,7 +19,7 @@ const AstRenameSymbolInputSchema = z.object({
|
|
|
18
19
|
.describe("Permit a plan with new TypeScript errors after explicit review."),
|
|
19
20
|
});
|
|
20
21
|
export function registerRenameSymbol(server) {
|
|
21
|
-
server.registerTool(
|
|
22
|
+
server.registerTool(TOOL_NAME, {
|
|
22
23
|
title: "Prepare a project-wide structural rename",
|
|
23
24
|
description: "Prepares an exact hash-bound rename plan without writing. Review the preview and apply its operation_id with ast_apply_operation.",
|
|
24
25
|
inputSchema: AstRenameSymbolInputSchema,
|
|
@@ -45,7 +46,9 @@ export function registerRenameSymbol(server) {
|
|
|
45
46
|
return structuredResult(serializePreparedOperation(operation));
|
|
46
47
|
}
|
|
47
48
|
catch (error) {
|
|
48
|
-
return errorResult(error, createToolErrorContext(
|
|
49
|
+
return errorResult(error, createToolErrorContext(TOOL_NAME, project_root));
|
|
49
50
|
}
|
|
50
51
|
});
|
|
51
52
|
}
|
|
53
|
+
// prettier-ignore
|
|
54
|
+
export const toolDescriptor = Object.freeze({ name: TOOL_NAME, register: registerRenameSymbol, compatibility: "required", effect: "prepare", batch: "prepare", directOutputFormats: Object.freeze(["json"]) });
|
|
@@ -3,6 +3,7 @@ import { prepareReplaceBody } from "../services/operations.js";
|
|
|
3
3
|
import { createRequestContext } from "../services/request-context.js";
|
|
4
4
|
import { PreparedOperationOutputSchema, serializePreparedOperation } from "./operation-schema.js";
|
|
5
5
|
import { createToolErrorContext, errorResult, structuredResult } from "./result.js";
|
|
6
|
+
const TOOL_NAME = "ast_replace_symbol_body";
|
|
6
7
|
const AstReplaceSymbolBodyInputSchema = z.object({
|
|
7
8
|
project_root: z.string(),
|
|
8
9
|
file_path: z.string(),
|
|
@@ -18,7 +19,7 @@ const AstReplaceSymbolBodyInputSchema = z.object({
|
|
|
18
19
|
.describe("Permit a plan with new TypeScript errors after explicit review."),
|
|
19
20
|
});
|
|
20
21
|
export function registerReplaceSymbolBody(server) {
|
|
21
|
-
server.registerTool(
|
|
22
|
+
server.registerTool(TOOL_NAME, {
|
|
22
23
|
title: "Prepare an exact function-body replacement",
|
|
23
24
|
description: "Prepares a hash-bound body replacement while preserving the signature. Supports declarations, methods, accessors and function-valued variables/properties.",
|
|
24
25
|
inputSchema: AstReplaceSymbolBodyInputSchema,
|
|
@@ -45,7 +46,9 @@ export function registerReplaceSymbolBody(server) {
|
|
|
45
46
|
return structuredResult(serializePreparedOperation(operation));
|
|
46
47
|
}
|
|
47
48
|
catch (error) {
|
|
48
|
-
return errorResult(error, createToolErrorContext(
|
|
49
|
+
return errorResult(error, createToolErrorContext(TOOL_NAME, project_root));
|
|
49
50
|
}
|
|
50
51
|
});
|
|
51
52
|
}
|
|
53
|
+
// prettier-ignore
|
|
54
|
+
export const toolDescriptor = Object.freeze({ name: TOOL_NAME, register: registerReplaceSymbolBody, compatibility: "required", effect: "prepare", batch: "prepare", directOutputFormats: Object.freeze(["json"]) });
|
|
@@ -3,6 +3,7 @@ import { prepareScaffoldClass } from "../services/operations.js";
|
|
|
3
3
|
import { createRequestContext } from "../services/request-context.js";
|
|
4
4
|
import { createToolErrorContext, errorResult, structuredResult } from "./result.js";
|
|
5
5
|
import { PreparedOperationOutputSchema, serializePreparedOperation } from "./operation-schema.js";
|
|
6
|
+
const TOOL_NAME = "ast_scaffold_class";
|
|
6
7
|
const IdentifierSchema = z.string().min(1).max(200);
|
|
7
8
|
const TypeTextSchema = z.string().min(1).max(10_000);
|
|
8
9
|
const AccessSchema = z.enum(["public", "protected", "private"]);
|
|
@@ -111,7 +112,7 @@ export function registerScaffoldClass(server) {
|
|
|
111
112
|
// The SDK compatibility overload exceeds TypeScript's instantiation depth for this schema.
|
|
112
113
|
// Keep the complete runtime schema and isolate only the registrar type.
|
|
113
114
|
const registerTool = server.registerTool.bind(server);
|
|
114
|
-
registerTool(
|
|
115
|
+
registerTool(TOOL_NAME, {
|
|
115
116
|
title: "Prepare Class Scaffold",
|
|
116
117
|
description: "Prepares a hash-bound new TypeScript class file without writing it. Each method body throws an explicit not-implemented error. Review the diff, then apply the returned operation_id and plan_hash with ast_apply_operation.",
|
|
117
118
|
inputSchema: ScaffoldClassInputSchema,
|
|
@@ -141,7 +142,9 @@ export function registerScaffoldClass(server) {
|
|
|
141
142
|
return structuredResult(structuredContent);
|
|
142
143
|
}
|
|
143
144
|
catch (error) {
|
|
144
|
-
return errorResult(error, createToolErrorContext(
|
|
145
|
+
return errorResult(error, createToolErrorContext(TOOL_NAME, args.project_root));
|
|
145
146
|
}
|
|
146
147
|
});
|
|
147
148
|
}
|
|
149
|
+
// prettier-ignore
|
|
150
|
+
export const toolDescriptor = Object.freeze({ name: TOOL_NAME, register: registerScaffoldClass, compatibility: "required", effect: "prepare", batch: "prepare", directOutputFormats: Object.freeze(["json"]) });
|
|
@@ -4,6 +4,7 @@ import { withProject, reportSymbolIndexFailure } from "../services/project.js";
|
|
|
4
4
|
import { createRequestContext } from "../services/request-context.js";
|
|
5
5
|
import { searchProjectSymbolsPage, searchProjectSymbolsPageWithIndex, } from "../services/symbols.js";
|
|
6
6
|
import { createToolErrorContext, errorResult, formattedResult, ToolOutputFormatInputSchema, } from "./result.js";
|
|
7
|
+
const TOOL_NAME = "ast_search_symbols";
|
|
7
8
|
const SEARCH_DEFAULT_LIMIT = 20;
|
|
8
9
|
const SearchDetailSchema = z.enum(["selectors", "summary", "full"]).default("summary");
|
|
9
10
|
const AstSearchSymbolsInputSchema = z.object({
|
|
@@ -77,7 +78,7 @@ function projectSymbols(detail, symbols) {
|
|
|
77
78
|
return symbols.map(({ file, selector, kind }) => ({ file, selector, kind }));
|
|
78
79
|
}
|
|
79
80
|
export function registerSearchSymbols(server) {
|
|
80
|
-
server.registerTool(
|
|
81
|
+
server.registerTool(TOOL_NAME, {
|
|
81
82
|
title: "Search project symbols",
|
|
82
83
|
description: "Ranks structural declarations and returns exact file/symbol selectors for downstream AST tools.",
|
|
83
84
|
inputSchema: AstSearchSymbolsInputSchema,
|
|
@@ -108,7 +109,9 @@ export function registerSearchSymbols(server) {
|
|
|
108
109
|
return formattedResult(outputSchema, structuredContent, output_format);
|
|
109
110
|
}
|
|
110
111
|
catch (error) {
|
|
111
|
-
return errorResult(error, createToolErrorContext(
|
|
112
|
+
return errorResult(error, createToolErrorContext(TOOL_NAME, project_root));
|
|
112
113
|
}
|
|
113
114
|
});
|
|
114
115
|
}
|
|
116
|
+
// prettier-ignore
|
|
117
|
+
export const toolDescriptor = Object.freeze({ name: TOOL_NAME, register: registerSearchSymbols, compatibility: "required", effect: "read", batch: "read", directOutputFormats: Object.freeze(["json", "toon"]) });
|
package/dist/worker-runtime.js
CHANGED
|
@@ -14,11 +14,11 @@ export async function runStdioServer(options = {}) {
|
|
|
14
14
|
prepareProjectRuntimeForStartup();
|
|
15
15
|
const runtimeActivity = options.runtimeActivity ?? new RuntimeActivityTracker();
|
|
16
16
|
runtimeActivity.prepareForStartup();
|
|
17
|
-
const
|
|
17
|
+
const runtimePolicy = options.runtimePolicy ?? readRuntimePolicy();
|
|
18
|
+
const server = options.server ?? createServer({ runtimeActivity, denyApply: runtimePolicy.denyApply });
|
|
18
19
|
const transport = options.transport ?? new StdioServerTransport();
|
|
19
20
|
const send = transport.send.bind(transport);
|
|
20
21
|
transport.send = (message, sendOptions) => runtimeActivity.trackSend(() => send(message, sendOptions));
|
|
21
|
-
const runtimePolicy = options.runtimePolicy ?? readRuntimePolicy();
|
|
22
22
|
const installProcessHandlers = options.installProcessHandlers ?? true;
|
|
23
23
|
const exit = options.exit ?? ((code) => process.exit(code));
|
|
24
24
|
const protocol = server.server;
|