@yinuo-ngm/mcp-server 0.1.2 → 0.1.4
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 +191 -208
- package/lib/audit/audit-event.d.ts +14 -0
- package/lib/audit/audit-event.js +2 -0
- package/lib/audit/audit-log.service.d.ts +7 -0
- package/lib/audit/audit-log.service.js +187 -0
- package/lib/audit/redact.d.ts +3 -0
- package/lib/audit/redact.js +28 -0
- package/lib/catalog/capabilities/blocked-local-actions.d.ts +1 -0
- package/lib/catalog/capabilities/blocked-local-actions.js +18 -0
- package/lib/catalog/capabilities/frontend-standard.d.ts +2 -0
- package/lib/catalog/capabilities/frontend-standard.js +36 -0
- package/lib/catalog/capabilities/hub-v2.d.ts +2 -0
- package/lib/catalog/capabilities/hub-v2.js +34 -0
- package/lib/catalog/capabilities/nginx.d.ts +2 -0
- package/lib/catalog/capabilities/nginx.js +23 -0
- package/lib/catalog/capabilities/project.d.ts +2 -0
- package/lib/catalog/capabilities/project.js +23 -0
- package/lib/catalog/capabilities/router.d.ts +2 -0
- package/lib/catalog/capabilities/router.js +11 -0
- package/lib/catalog/capabilities/runtime.d.ts +2 -0
- package/lib/catalog/capabilities/runtime.js +17 -0
- package/lib/catalog/capabilities/workspace.d.ts +2 -0
- package/lib/catalog/capabilities/workspace.js +23 -0
- package/lib/catalog/helpers.d.ts +3 -0
- package/lib/catalog/helpers.js +42 -0
- package/lib/catalog/index.d.ts +4 -0
- package/lib/catalog/index.js +23 -0
- package/lib/catalog/tools/frontend-standard.d.ts +2 -0
- package/lib/catalog/tools/frontend-standard.js +166 -0
- package/lib/catalog/tools/hub-v2-api.d.ts +2 -0
- package/lib/catalog/tools/hub-v2-api.js +124 -0
- package/lib/catalog/tools/hub-v2-docs.d.ts +2 -0
- package/lib/catalog/tools/hub-v2-docs.js +40 -0
- package/lib/catalog/tools/nginx.d.ts +2 -0
- package/lib/catalog/tools/nginx.js +82 -0
- package/lib/catalog/tools/project.d.ts +2 -0
- package/lib/catalog/tools/project.js +124 -0
- package/lib/catalog/tools/router.d.ts +2 -0
- package/lib/catalog/tools/router.js +26 -0
- package/lib/catalog/tools/runtime.d.ts +2 -0
- package/lib/catalog/tools/runtime.js +40 -0
- package/lib/catalog/tools/workspace.d.ts +2 -0
- package/lib/catalog/tools/workspace.js +75 -0
- package/lib/catalog/types.d.ts +15 -0
- package/lib/catalog/types.js +2 -0
- package/lib/context/create-tool-context.js +11 -10
- package/lib/context/local-server-client.d.ts +2 -0
- package/lib/context/local-server-client.js +174 -0
- package/lib/context/tool-context.d.ts +36 -0
- package/lib/doctor.d.ts +8 -0
- package/lib/doctor.js +194 -0
- package/lib/errors/error-codes.d.ts +12 -0
- package/lib/errors/error-codes.js +14 -0
- package/lib/errors/mcp-tool-error.d.ts +8 -0
- package/lib/errors/mcp-tool-error.js +14 -0
- package/lib/filesystem/project-files.d.ts +18 -0
- package/lib/filesystem/project-files.js +112 -0
- package/lib/git/local-git-read-service.d.ts +2 -0
- package/lib/git/local-git-read-service.js +96 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +4 -0
- package/lib/policy/assert-tool-policy.js +10 -1
- package/lib/register-tools.js +67 -10
- package/lib/registry/tool-names.d.ts +95 -0
- package/lib/registry/tool-names.js +97 -0
- package/lib/services/path-guard.service.d.ts +4 -0
- package/lib/services/path-guard.service.js +75 -0
- package/lib/services/permission.service.d.ts +5 -0
- package/lib/services/permission.service.js +38 -0
- package/lib/services/project-resolver.service.d.ts +32 -0
- package/lib/services/project-resolver.service.js +95 -0
- package/lib/standard/frontend-standard.default.d.ts +2 -0
- package/lib/standard/frontend-standard.default.js +51 -0
- package/lib/standard/frontend-standard.schema.d.ts +196 -0
- package/lib/standard/frontend-standard.schema.js +61 -0
- package/lib/standard/frontend-standard.service.d.ts +79 -0
- package/lib/standard/frontend-standard.service.js +115 -0
- package/lib/standard/project-scan.d.ts +9 -0
- package/lib/standard/project-scan.js +91 -0
- package/lib/standard/validators/angular-structure.validator.d.ts +4 -0
- package/lib/standard/validators/angular-structure.validator.js +75 -0
- package/lib/standard/validators/component.validator.d.ts +4 -0
- package/lib/standard/validators/component.validator.js +94 -0
- package/lib/standard/validators/git.validator.d.ts +8 -0
- package/lib/standard/validators/git.validator.js +32 -0
- package/lib/standard/validators/review.validator.d.ts +15 -0
- package/lib/standard/validators/review.validator.js +67 -0
- package/lib/standard/validators/test.validator.d.ts +19 -0
- package/lib/standard/validators/test.validator.js +89 -0
- package/lib/tool-catalog.d.ts +2 -0
- package/lib/tool-catalog.js +6 -0
- package/lib/tools/angular/angular-standard.tools.d.ts +2 -0
- package/lib/tools/angular/angular-standard.tools.js +53 -0
- package/lib/tools/angular/index.d.ts +1 -0
- package/lib/tools/angular/index.js +5 -0
- package/lib/tools/capability.tools.d.ts +2 -0
- package/lib/tools/capability.tools.js +205 -0
- package/lib/tools/controlled/index.d.ts +2 -0
- package/lib/tools/controlled/index.js +13 -0
- package/lib/tools/controlled/local-server.d.ts +6 -0
- package/lib/tools/controlled/local-server.js +17 -0
- package/lib/tools/controlled/operation-policy.d.ts +22 -0
- package/lib/tools/controlled/operation-policy.js +50 -0
- package/lib/tools/controlled/operation-result.d.ts +30 -0
- package/lib/tools/controlled/operation-result.js +33 -0
- package/lib/tools/controlled/schemas.d.ts +159 -0
- package/lib/tools/controlled/schemas.js +49 -0
- package/lib/tools/controlled.tools.d.ts +1 -0
- package/lib/tools/controlled.tools.js +5 -0
- package/lib/tools/file-write.tools.d.ts +2 -0
- package/lib/tools/file-write.tools.js +70 -0
- package/lib/tools/git.tools.js +109 -8
- package/lib/tools/hub-v2/client.d.ts +6 -1
- package/lib/tools/hub-v2/client.js +15 -0
- package/lib/tools/hub-v2/config/config-paths.d.ts +2 -0
- package/lib/tools/hub-v2/config/config-paths.js +17 -0
- package/lib/tools/hub-v2/config/env.d.ts +1 -0
- package/lib/tools/hub-v2/config/env.js +12 -0
- package/lib/tools/hub-v2/config/index.d.ts +8 -0
- package/lib/tools/hub-v2/config/index.js +18 -0
- package/lib/tools/hub-v2/config/jsonc.d.ts +5 -0
- package/lib/tools/hub-v2/config/jsonc.js +86 -0
- package/lib/tools/hub-v2/config/load-config.d.ts +18 -0
- package/lib/tools/hub-v2/config/load-config.js +93 -0
- package/lib/tools/hub-v2/config/project-selector.d.ts +5 -0
- package/lib/tools/hub-v2/config/project-selector.js +92 -0
- package/lib/tools/hub-v2/config/resolve-context.d.ts +13 -0
- package/lib/tools/hub-v2/config/resolve-context.js +33 -0
- package/lib/tools/hub-v2/docs.tools.js +138 -4
- package/lib/tools/hub-v2/index.js +2 -0
- package/lib/tools/hub-v2/issues-workflow.tools.d.ts +2 -0
- package/lib/tools/hub-v2/issues-workflow.tools.js +199 -0
- package/lib/tools/hub-v2/issues.tools.js +96 -6
- package/lib/tools/hub-v2/projects.tools.js +16 -3
- package/lib/tools/hub-v2/raw.d.ts +8 -0
- package/lib/tools/hub-v2/raw.js +33 -0
- package/lib/tools/hub-v2/rd.tools.js +167 -8
- package/lib/tools/hub-v2/schemas.d.ts +668 -71
- package/lib/tools/hub-v2/schemas.js +152 -1
- package/lib/tools/hub-v2/upload.tools.js +53 -5
- package/lib/tools/index.d.ts +1 -0
- package/lib/tools/index.js +22 -0
- package/lib/tools/log.tools.js +33 -6
- package/lib/tools/nginx/index.d.ts +1 -0
- package/lib/tools/nginx/index.js +5 -0
- package/lib/tools/nginx/nginx-control.tools.d.ts +2 -0
- package/lib/tools/nginx/nginx-control.tools.js +133 -0
- package/lib/tools/nginx/nginx-proxy.d.ts +24 -0
- package/lib/tools/nginx/nginx-proxy.js +154 -0
- package/lib/tools/nginx.tools.d.ts +2 -0
- package/lib/tools/nginx.tools.js +111 -0
- package/lib/tools/project/index.d.ts +2 -0
- package/lib/tools/project/index.js +7 -0
- package/lib/tools/project/launch-status.d.ts +10 -0
- package/lib/tools/project/launch-status.js +78 -0
- package/lib/tools/project/local-diagnostics.d.ts +19 -0
- package/lib/tools/project/local-diagnostics.js +97 -0
- package/lib/tools/project/observe-redaction.d.ts +3 -0
- package/lib/tools/project/observe-redaction.js +25 -0
- package/lib/tools/project/observe-runtime.d.ts +72 -0
- package/lib/tools/project/observe-runtime.js +147 -0
- package/lib/tools/project/project-control.tools.d.ts +2 -0
- package/lib/tools/project/project-control.tools.js +216 -0
- package/lib/tools/project/project-observe.tools.d.ts +2 -0
- package/lib/tools/project/project-observe.tools.js +191 -0
- package/lib/tools/project/runtime-config.d.ts +7 -0
- package/lib/tools/project/runtime-config.js +50 -0
- package/lib/tools/project-observe.tools.d.ts +1 -0
- package/lib/tools/project-observe.tools.js +5 -0
- package/lib/tools/project.tools.d.ts +8 -0
- package/lib/tools/project.tools.js +97 -6
- package/lib/tools/proxy.tools.js +4 -4
- package/lib/tools/review/index.d.ts +1 -0
- package/lib/tools/review/index.js +5 -0
- package/lib/tools/review/review.tools.d.ts +2 -0
- package/lib/tools/review/review.tools.js +152 -0
- package/lib/tools/runtime/index.d.ts +1 -0
- package/lib/tools/runtime/index.js +5 -0
- package/lib/tools/runtime/runtime-control.tools.d.ts +2 -0
- package/lib/tools/runtime/runtime-control.tools.js +89 -0
- package/lib/tools/runtime.tools.js +41 -4
- package/lib/tools/standard/index.d.ts +1 -0
- package/lib/tools/standard/index.js +5 -0
- package/lib/tools/standard/standard.tools.d.ts +2 -0
- package/lib/tools/standard/standard.tools.js +91 -0
- package/lib/tools/task.tools.js +44 -9
- package/lib/tools/test/index.d.ts +1 -0
- package/lib/tools/test/index.js +5 -0
- package/lib/tools/test/test-standard.tools.d.ts +2 -0
- package/lib/tools/test/test-standard.tools.js +51 -0
- package/lib/tools/tool-catalog.d.ts +2 -0
- package/lib/tools/tool-catalog.js +7 -0
- package/lib/tools/workflow/frontend-workflow.tools.d.ts +2 -0
- package/lib/tools/workflow/frontend-workflow.tools.js +364 -0
- package/lib/tools/workflow/index.d.ts +1 -0
- package/lib/tools/workflow/index.js +5 -0
- package/lib/tools/workspace-package.d.ts +22 -0
- package/lib/tools/workspace-package.js +130 -0
- package/lib/tools/workspace.tools.d.ts +7 -0
- package/lib/tools/workspace.tools.js +336 -0
- package/lib/utils/errors.js +6 -1
- package/lib/utils/result.d.ts +9 -0
- package/lib/utils/result.js +9 -0
- package/lib/workflow/frontend-task.schema.d.ts +83 -0
- package/lib/workflow/frontend-task.schema.js +25 -0
- package/lib/workflow/frontend-task.service.d.ts +57 -0
- package/lib/workflow/frontend-task.service.js +195 -0
- package/lib/workflow/workflow-status.d.ts +2 -0
- package/lib/workflow/workflow-status.js +14 -0
- package/lib/workflow/workflow-transition.d.ts +9 -0
- package/lib/workflow/workflow-transition.js +38 -0
- package/package.json +5 -3
- package/lib/tools/hub-v2/config.d.ts +0 -34
- package/lib/tools/hub-v2/config.js +0 -297
|
@@ -39,10 +39,18 @@ exports.projectTools = projectTools;
|
|
|
39
39
|
const path = __importStar(require("path"));
|
|
40
40
|
const zod_1 = require("zod");
|
|
41
41
|
const result_1 = require("../utils/result");
|
|
42
|
+
const workspace_tools_1 = require("./workspace.tools");
|
|
43
|
+
const project_resolver_service_1 = require("../services/project-resolver.service");
|
|
42
44
|
exports.projectLocatorSchema = zod_1.z.object({
|
|
43
45
|
projectId: zod_1.z.string().trim().min(1).optional(),
|
|
44
46
|
projectPath: zod_1.z.string().trim().min(1).optional(),
|
|
45
47
|
}).strict();
|
|
48
|
+
const projectFindSchema = zod_1.z.object({
|
|
49
|
+
query: zod_1.z.string().trim().min(1).optional(),
|
|
50
|
+
framework: zod_1.z.string().trim().min(1).optional(),
|
|
51
|
+
packageManager: zod_1.z.enum(["npm", "pnpm", "yarn"]).optional(),
|
|
52
|
+
projectPath: zod_1.z.string().trim().min(1).optional(),
|
|
53
|
+
}).strict();
|
|
46
54
|
async function resolveProject(context, locator) {
|
|
47
55
|
if (locator.projectId) {
|
|
48
56
|
return context.services.core.project.get(locator.projectId);
|
|
@@ -66,6 +74,7 @@ function toProjectSummary(project) {
|
|
|
66
74
|
return {
|
|
67
75
|
id: project.id,
|
|
68
76
|
name: project.name,
|
|
77
|
+
path: project.root.replace(/\\/g, "/"),
|
|
69
78
|
root: project.root,
|
|
70
79
|
createdAt: project.createdAt,
|
|
71
80
|
updatedAt: project.updatedAt,
|
|
@@ -82,6 +91,22 @@ function toProjectSummary(project) {
|
|
|
82
91
|
assets: project.assets,
|
|
83
92
|
};
|
|
84
93
|
}
|
|
94
|
+
function projectResolver(context) {
|
|
95
|
+
return context.services.projectResolver ?? new project_resolver_service_1.ProjectResolverService(context.services.core.project);
|
|
96
|
+
}
|
|
97
|
+
function scriptNames(project) {
|
|
98
|
+
return Object.keys(project.scripts ?? {}).sort();
|
|
99
|
+
}
|
|
100
|
+
function toMcpProjectItem(project) {
|
|
101
|
+
return {
|
|
102
|
+
id: project.id,
|
|
103
|
+
name: project.name,
|
|
104
|
+
path: project.root.replace(/\\/g, "/"),
|
|
105
|
+
framework: project.framework,
|
|
106
|
+
favorite: project.isFavorite,
|
|
107
|
+
scripts: scriptNames(project),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
85
110
|
function toProjectScripts(project) {
|
|
86
111
|
return {
|
|
87
112
|
id: project.id,
|
|
@@ -96,33 +121,99 @@ function toProjectScripts(project) {
|
|
|
96
121
|
function projectTools() {
|
|
97
122
|
return [
|
|
98
123
|
{
|
|
99
|
-
name: "
|
|
124
|
+
name: "ngm_project_list",
|
|
125
|
+
description: "List registered ng-manager projects by projectId. Prefer this MCP read tool before direct shell discovery because it uses the ng-manager project registry and does not scan arbitrary workspace roots.",
|
|
126
|
+
riskLevel: "read",
|
|
127
|
+
inputSchema: zod_1.z.object({}).strict(),
|
|
128
|
+
async handler(_args, context) {
|
|
129
|
+
const projects = await projectResolver(context).listProjects();
|
|
130
|
+
return (0, result_1.ok)("ngm_project_list", projects.map(toMcpProjectItem));
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
name: "ngm_project_managed_list",
|
|
100
135
|
description: "List projects managed by ng-manager.",
|
|
101
136
|
riskLevel: "read",
|
|
102
137
|
inputSchema: zod_1.z.object({}).strict(),
|
|
103
138
|
async handler(_args, context) {
|
|
104
139
|
const projects = await context.services.core.project.list();
|
|
105
|
-
return (0, result_1.ok)("
|
|
140
|
+
return (0, result_1.ok)("ngm_project_managed_list", projects.map(toProjectSummary));
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
name: "ngm_project_find",
|
|
145
|
+
description: "Find ng-manager local projects by name, path, framework, package manager, or repository URL.",
|
|
146
|
+
riskLevel: "read",
|
|
147
|
+
inputSchema: projectFindSchema,
|
|
148
|
+
async handler(args, context) {
|
|
149
|
+
const projects = await context.services.core.project.list();
|
|
150
|
+
const query = args.query?.toLowerCase();
|
|
151
|
+
const requestedPath = args.projectPath ? normalizeFsPath(args.projectPath) : "";
|
|
152
|
+
const matched = projects.filter((project) => {
|
|
153
|
+
if (args.packageManager && project.packageManager !== args.packageManager)
|
|
154
|
+
return false;
|
|
155
|
+
if (args.framework && String(project.framework ?? "").toLowerCase() !== args.framework.toLowerCase())
|
|
156
|
+
return false;
|
|
157
|
+
if (requestedPath && !normalizeFsPath(project.root).includes(requestedPath))
|
|
158
|
+
return false;
|
|
159
|
+
if (!query)
|
|
160
|
+
return true;
|
|
161
|
+
const text = [
|
|
162
|
+
project.id,
|
|
163
|
+
project.name,
|
|
164
|
+
project.root,
|
|
165
|
+
project.framework,
|
|
166
|
+
project.packageManager,
|
|
167
|
+
project.repoUrl,
|
|
168
|
+
project.repoPageUrl,
|
|
169
|
+
]
|
|
170
|
+
.filter(Boolean)
|
|
171
|
+
.join(" ")
|
|
172
|
+
.toLowerCase();
|
|
173
|
+
return text.includes(query);
|
|
174
|
+
});
|
|
175
|
+
return (0, result_1.ok)("ngm_project_find", matched.map(toProjectSummary));
|
|
106
176
|
},
|
|
107
177
|
},
|
|
108
178
|
{
|
|
109
|
-
name: "
|
|
179
|
+
name: "ngm_project_get",
|
|
110
180
|
description: "Get one ng-manager project by projectId or projectPath.",
|
|
111
181
|
riskLevel: "read",
|
|
112
182
|
inputSchema: exports.projectLocatorSchema,
|
|
113
183
|
async handler(args, context) {
|
|
114
184
|
const project = await resolveProject(context, args);
|
|
115
|
-
return (0, result_1.ok)("
|
|
185
|
+
return (0, result_1.ok)("ngm_project_get", toProjectSummary(project));
|
|
116
186
|
},
|
|
117
187
|
},
|
|
118
188
|
{
|
|
119
|
-
name: "
|
|
189
|
+
name: "ngm_project_get_scripts",
|
|
120
190
|
description: "Get package scripts and runtime hints for one ng-manager project.",
|
|
121
191
|
riskLevel: "read",
|
|
122
192
|
inputSchema: exports.projectLocatorSchema,
|
|
123
193
|
async handler(args, context) {
|
|
124
194
|
const project = await resolveProject(context, args);
|
|
125
|
-
return (0, result_1.ok)("
|
|
195
|
+
return (0, result_1.ok)("ngm_project_get_scripts", toProjectScripts(project));
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
name: "ngm_project_read_package_json",
|
|
200
|
+
description: "Read package.json metadata for one registered ng-manager local project without running scripts.",
|
|
201
|
+
riskLevel: "read",
|
|
202
|
+
inputSchema: exports.projectLocatorSchema,
|
|
203
|
+
async handler(args, context) {
|
|
204
|
+
const project = await resolveProject(context, args);
|
|
205
|
+
const packageJson = await (0, workspace_tools_1.readWorkspacePackageJson)(context.workspaceRoot, project.root);
|
|
206
|
+
return (0, result_1.ok)("ngm_project_read_package_json", {
|
|
207
|
+
project: {
|
|
208
|
+
id: project.id,
|
|
209
|
+
name: project.name,
|
|
210
|
+
root: project.root,
|
|
211
|
+
packageManager: project.packageManager,
|
|
212
|
+
runtime: project.runtime,
|
|
213
|
+
nodeVersion: project.nodeVersion,
|
|
214
|
+
},
|
|
215
|
+
packageJson,
|
|
216
|
+
});
|
|
126
217
|
},
|
|
127
218
|
},
|
|
128
219
|
];
|
package/lib/tools/proxy.tools.js
CHANGED
|
@@ -9,7 +9,7 @@ const proxyValidateSchema = zod_1.z.object({
|
|
|
9
9
|
function proxyTools() {
|
|
10
10
|
return [
|
|
11
11
|
{
|
|
12
|
-
name: "
|
|
12
|
+
name: "ngm_proxy_list",
|
|
13
13
|
description: "List current ng-manager Nginx/proxy binding, status, servers, and upstreams.",
|
|
14
14
|
riskLevel: "read",
|
|
15
15
|
inputSchema: zod_1.z.object({}).strict(),
|
|
@@ -24,7 +24,7 @@ function proxyTools() {
|
|
|
24
24
|
nginx.server.getAllServers().catch(() => []),
|
|
25
25
|
nginx.module.getUpstreams().catch(() => []),
|
|
26
26
|
]);
|
|
27
|
-
return (0, result_1.ok)("
|
|
27
|
+
return (0, result_1.ok)("ngm_proxy_list", {
|
|
28
28
|
instance,
|
|
29
29
|
status,
|
|
30
30
|
servers,
|
|
@@ -33,13 +33,13 @@ function proxyTools() {
|
|
|
33
33
|
},
|
|
34
34
|
},
|
|
35
35
|
{
|
|
36
|
-
name: "
|
|
36
|
+
name: "ngm_proxy_validate",
|
|
37
37
|
description: "Validate the current or supplied ng-manager Nginx/proxy config without reload.",
|
|
38
38
|
riskLevel: "read",
|
|
39
39
|
inputSchema: proxyValidateSchema,
|
|
40
40
|
async handler(args, context) {
|
|
41
41
|
const validation = await context.services.core.nginx.config.validateConfig(args.configText);
|
|
42
|
-
return (0, result_1.ok)("
|
|
42
|
+
return (0, result_1.ok)("ngm_proxy_validate", validation);
|
|
43
43
|
},
|
|
44
44
|
},
|
|
45
45
|
];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { reviewTools } from "./review.tools";
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.reviewTools = void 0;
|
|
4
|
+
var review_tools_1 = require("./review.tools");
|
|
5
|
+
Object.defineProperty(exports, "reviewTools", { enumerable: true, get: function () { return review_tools_1.reviewTools; } });
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.reviewTools = reviewTools;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const result_1 = require("../../utils/result");
|
|
6
|
+
const project_files_1 = require("../../filesystem/project-files");
|
|
7
|
+
const operation_result_1 = require("../controlled/operation-result");
|
|
8
|
+
const operation_policy_1 = require("../controlled/operation-policy");
|
|
9
|
+
const frontend_standard_service_1 = require("../../standard/frontend-standard.service");
|
|
10
|
+
const review_validator_1 = require("../../standard/validators/review.validator");
|
|
11
|
+
const frontend_task_service_1 = require("../../workflow/frontend-task.service");
|
|
12
|
+
const workflow_transition_1 = require("../../workflow/workflow-transition");
|
|
13
|
+
const projectSchema = zod_1.z.object({
|
|
14
|
+
projectId: zod_1.z.string().trim().min(1).optional(),
|
|
15
|
+
projectPath: zod_1.z.string().trim().min(1).optional(),
|
|
16
|
+
}).strict();
|
|
17
|
+
const changedFilesSchema = projectSchema.extend({
|
|
18
|
+
changedFiles: zod_1.z.array(zod_1.z.string().trim().min(1)).optional(),
|
|
19
|
+
}).strict();
|
|
20
|
+
const reportSchema = changedFilesSchema.extend({
|
|
21
|
+
taskId: zod_1.z.string().trim().min(1),
|
|
22
|
+
confirm: zod_1.z.boolean().optional(),
|
|
23
|
+
dryRun: zod_1.z.boolean().optional(),
|
|
24
|
+
}).strict();
|
|
25
|
+
async function readChangedFiles(context, args, projectRoot) {
|
|
26
|
+
if (args.changedFiles)
|
|
27
|
+
return args.changedFiles.map((item) => item.replace(/\\/g, "/"));
|
|
28
|
+
const gitArgs = { ...args, projectPath: projectRoot };
|
|
29
|
+
if (!context.services.git.changedFiles)
|
|
30
|
+
return [];
|
|
31
|
+
try {
|
|
32
|
+
return await context.services.git.changedFiles(gitArgs);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function reviewTools() {
|
|
39
|
+
return [
|
|
40
|
+
{
|
|
41
|
+
name: "ngm_review_scan_changed_files",
|
|
42
|
+
description: "Read changed files from a fixed read-only git status command, or echo provided changedFiles.",
|
|
43
|
+
riskLevel: "read",
|
|
44
|
+
inputSchema: changedFilesSchema,
|
|
45
|
+
async handler(args, context) {
|
|
46
|
+
const project = await (0, project_files_1.resolveProjectRoot)(context, args);
|
|
47
|
+
const changedFiles = await readChangedFiles(context, args, project.projectRoot);
|
|
48
|
+
return (0, result_1.ok)("ngm_review_scan_changed_files", { project, changedFiles });
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: "ngm_review_generate_checklist",
|
|
53
|
+
description: "Generate a frontend code review checklist for the current changed files.",
|
|
54
|
+
riskLevel: "read",
|
|
55
|
+
inputSchema: changedFilesSchema,
|
|
56
|
+
async handler(args, context) {
|
|
57
|
+
const project = await (0, project_files_1.resolveProjectRoot)(context, args);
|
|
58
|
+
const changedFiles = await readChangedFiles(context, args, project.projectRoot);
|
|
59
|
+
return (0, result_1.ok)("ngm_review_generate_checklist", { changedFiles, checklist: (0, review_validator_1.reviewChecklist)(changedFiles) });
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: "ngm_review_detect_risks",
|
|
64
|
+
description: "Detect lightweight review risks in changed frontend files.",
|
|
65
|
+
riskLevel: "read",
|
|
66
|
+
inputSchema: changedFilesSchema,
|
|
67
|
+
async handler(args, context) {
|
|
68
|
+
const project = await (0, project_files_1.resolveProjectRoot)(context, args);
|
|
69
|
+
const loaded = await (0, frontend_standard_service_1.loadFrontendStandard)(project);
|
|
70
|
+
const changedFiles = await readChangedFiles(context, args, project.projectRoot);
|
|
71
|
+
const files = await (0, frontend_standard_service_1.scanFrontendProject)(project.projectRoot);
|
|
72
|
+
return (0, result_1.ok)("ngm_review_detect_risks", {
|
|
73
|
+
changedFiles,
|
|
74
|
+
...(0, review_validator_1.detectReviewRisks)(files, changedFiles, loaded.standard),
|
|
75
|
+
});
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
name: "ngm_review_generate_report",
|
|
80
|
+
description: "Preview or write .ng-manager/reports/review-{taskId}.md with changed files, automated checks, risks, suggestions, and manual confirmation items.",
|
|
81
|
+
riskLevel: "write",
|
|
82
|
+
allowPreviewWhenBlocked: true,
|
|
83
|
+
deferPolicyToHandler: true,
|
|
84
|
+
isConfirmed: operation_result_1.isConfirmed,
|
|
85
|
+
inputSchema: reportSchema,
|
|
86
|
+
async handler(args, context) {
|
|
87
|
+
(0, project_files_1.validateSafeId)("taskId", args.taskId);
|
|
88
|
+
const project = await (0, project_files_1.resolveProjectRoot)(context, args);
|
|
89
|
+
const loaded = await (0, frontend_standard_service_1.loadFrontendStandard)(project);
|
|
90
|
+
const changedFiles = await readChangedFiles(context, args, project.projectRoot);
|
|
91
|
+
const files = await (0, frontend_standard_service_1.scanFrontendProject)(project.projectRoot);
|
|
92
|
+
const projectChecks = await (0, frontend_standard_service_1.validateFrontendProject)(project, loaded.standard);
|
|
93
|
+
const risks = (0, review_validator_1.detectReviewRisks)(files, changedFiles, loaded.standard);
|
|
94
|
+
const checklist = (0, review_validator_1.reviewChecklist)(changedFiles);
|
|
95
|
+
const markdown = (0, review_validator_1.generateReviewMarkdown)({
|
|
96
|
+
taskId: args.taskId,
|
|
97
|
+
changedFiles,
|
|
98
|
+
checks: Object.entries(projectChecks.checks).map(([title, check]) => ({
|
|
99
|
+
title,
|
|
100
|
+
status: check.status,
|
|
101
|
+
findings: check.findings,
|
|
102
|
+
})),
|
|
103
|
+
risks: risks.findings,
|
|
104
|
+
checklist,
|
|
105
|
+
});
|
|
106
|
+
const reportPath = (0, frontend_task_service_1.taskFile)(project.projectRoot, args.taskId, "review-report.md");
|
|
107
|
+
const safetyMessage = "Write frontend code review report under project .ng-manager/frontend-tasks.";
|
|
108
|
+
const preview = {
|
|
109
|
+
operation: (0, operation_result_1.operation)("preview", "write", "low", safetyMessage),
|
|
110
|
+
project,
|
|
111
|
+
taskId: args.taskId,
|
|
112
|
+
path: (0, project_files_1.projectRelativePath)(project.projectRoot, reportPath),
|
|
113
|
+
changedFiles,
|
|
114
|
+
markdown,
|
|
115
|
+
};
|
|
116
|
+
if (!(0, operation_result_1.isConfirmed)(args))
|
|
117
|
+
return (0, result_1.ok)("ngm_review_generate_report", preview);
|
|
118
|
+
const policyBlock = (0, operation_policy_1.requireWritePolicy)("low", safetyMessage);
|
|
119
|
+
if (policyBlock)
|
|
120
|
+
return (0, result_1.ok)("ngm_review_generate_report", policyBlock);
|
|
121
|
+
try {
|
|
122
|
+
const task = await (0, frontend_task_service_1.readFrontendTask)(project, args.taskId);
|
|
123
|
+
if (!(0, workflow_transition_1.canTransitionWorkflowStatus)(task.status, "review-ready")) {
|
|
124
|
+
return (0, result_1.ok)("ngm_review_generate_report", (0, operation_result_1.blocked)("write", "low", safetyMessage, (0, workflow_transition_1.workflowTransitionReason)(task.status, "review-ready")));
|
|
125
|
+
}
|
|
126
|
+
await (0, project_files_1.writeTextFile)(reportPath, markdown);
|
|
127
|
+
await (0, frontend_task_service_1.updateFrontendTask)(project, args.taskId, {
|
|
128
|
+
status: "review-ready",
|
|
129
|
+
changedFiles,
|
|
130
|
+
checks: {
|
|
131
|
+
standard: projectChecks.status === "passed" || projectChecks.status === "warning" || projectChecks.status === "failed" || projectChecks.status === "blocked" ? projectChecks.status : "pending",
|
|
132
|
+
test: projectChecks.checks.missingSpecs.status === "passed" || projectChecks.checks.missingSpecs.status === "warning" || projectChecks.checks.missingSpecs.status === "failed" || projectChecks.checks.missingSpecs.status === "blocked" ? projectChecks.checks.missingSpecs.status : "pending",
|
|
133
|
+
review: risks.status === "passed" || risks.status === "warning" || risks.status === "failed" || risks.status === "blocked" ? risks.status : "pending",
|
|
134
|
+
build: "pending",
|
|
135
|
+
},
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
return (0, result_1.ok)("ngm_review_generate_report", (0, operation_result_1.blocked)("write", "low", safetyMessage, error instanceof Error ? error.message : String(error)));
|
|
140
|
+
}
|
|
141
|
+
return (0, result_1.ok)("ngm_review_generate_report", {
|
|
142
|
+
...preview,
|
|
143
|
+
operation: (0, operation_result_1.operation)("executed", "write", "low", safetyMessage),
|
|
144
|
+
changedFiles: [
|
|
145
|
+
(0, project_files_1.projectRelativePath)(project.projectRoot, reportPath),
|
|
146
|
+
`.ng-manager/frontend-tasks/${args.taskId}/task.json`,
|
|
147
|
+
],
|
|
148
|
+
});
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
];
|
|
152
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { runtimeControlTools } from "./runtime-control.tools";
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runtimeControlTools = void 0;
|
|
4
|
+
var runtime_control_tools_1 = require("./runtime-control.tools");
|
|
5
|
+
Object.defineProperty(exports, "runtimeControlTools", { enumerable: true, get: function () { return runtime_control_tools_1.runtimeControlTools; } });
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runtimeControlTools = runtimeControlTools;
|
|
4
|
+
const operation_result_1 = require("../controlled/operation-result");
|
|
5
|
+
const result_1 = require("../../utils/result");
|
|
6
|
+
const local_server_1 = require("../controlled/local-server");
|
|
7
|
+
const operation_policy_1 = require("../controlled/operation-policy");
|
|
8
|
+
const schemas_1 = require("../controlled/schemas");
|
|
9
|
+
const runtime_config_1 = require("../project/runtime-config");
|
|
10
|
+
const project_resolver_service_1 = require("../../services/project-resolver.service");
|
|
11
|
+
const error_codes_1 = require("../../errors/error-codes");
|
|
12
|
+
function projectResolver(context) {
|
|
13
|
+
return context.services.projectResolver ?? new project_resolver_service_1.ProjectResolverService(context.services.core.project);
|
|
14
|
+
}
|
|
15
|
+
function runtimeControlTools() {
|
|
16
|
+
return [
|
|
17
|
+
{
|
|
18
|
+
name: "ngm_runtime_set_for_project",
|
|
19
|
+
description: "Skill ngm-runtime. Controlled write tool for binding a registered ng-manager projectId to a Node runtime config through the local ng-manager server. Prefer this over editing config files or shell profiles because it preserves server/UI state and audit. Previews by default; real write requires confirm=true and NGM_MCP_ALLOW_WRITE=true. It does not modify system PATH, nvm, shell profiles, or install runtimes.",
|
|
20
|
+
riskLevel: "write",
|
|
21
|
+
allowPreviewWhenBlocked: true,
|
|
22
|
+
deferPolicyToHandler: true,
|
|
23
|
+
isConfirmed: operation_result_1.isConfirmed,
|
|
24
|
+
inputSchema: schemas_1.setRuntimeSchema,
|
|
25
|
+
async handler(args, context) {
|
|
26
|
+
const confirmed = (0, operation_result_1.isConfirmed)(args);
|
|
27
|
+
if (confirmed) {
|
|
28
|
+
const policyBlock = (0, operation_policy_1.requireWritePolicy)("medium", `Set Node runtime binding for registered project "${args.projectId}".`);
|
|
29
|
+
if (policyBlock)
|
|
30
|
+
return (0, result_1.ok)("ngm_runtime_set_for_project", { ...(0, operation_result_1.controlledFields)("write", true, (0, operation_policy_1.requiredEnv)("write")), ...policyBlock });
|
|
31
|
+
}
|
|
32
|
+
const project = await projectResolver(context).resolveProject(args.projectId);
|
|
33
|
+
const nextRuntime = (0, runtime_config_1.toRuntimeConfig)(args.runtime);
|
|
34
|
+
(0, runtime_config_1.validateTargetRuntime)(nextRuntime);
|
|
35
|
+
const safetyMessage = `Set Node runtime binding for managed project "${project.name}".`;
|
|
36
|
+
const oldRuntime = (0, runtime_config_1.runtimeConfigForProject)(project);
|
|
37
|
+
let resolvedRuntime;
|
|
38
|
+
try {
|
|
39
|
+
resolvedRuntime = await context.services.core.nodeRuntime.resolveRuntime(nextRuntime);
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
return (0, result_1.ok)("ngm_runtime_set_for_project", (0, operation_result_1.blocked)("write", "medium", safetyMessage, "target runtime could not be resolved", {
|
|
43
|
+
error: error instanceof Error ? error.message : String(error),
|
|
44
|
+
nextStep: "Install or register the target Node runtime before binding the project.",
|
|
45
|
+
project: { id: project.id, name: project.name, root: project.root },
|
|
46
|
+
oldRuntime,
|
|
47
|
+
newRuntime: nextRuntime,
|
|
48
|
+
}));
|
|
49
|
+
}
|
|
50
|
+
const preview = {
|
|
51
|
+
...(0, operation_result_1.controlledFields)("write", confirmed, (0, operation_policy_1.requiredEnv)("write")),
|
|
52
|
+
operation: (0, operation_result_1.operation)("preview", "write", "medium", safetyMessage),
|
|
53
|
+
project: { id: project.id, name: project.name, root: project.root },
|
|
54
|
+
diff: { oldRuntime, newRuntime: nextRuntime },
|
|
55
|
+
resolvedRuntime,
|
|
56
|
+
};
|
|
57
|
+
if (!confirmed)
|
|
58
|
+
return (0, result_1.ok)("ngm_runtime_set_for_project", preview);
|
|
59
|
+
const serverCheck = await (0, local_server_1.requireLocalServer)(context);
|
|
60
|
+
if (!serverCheck.server) {
|
|
61
|
+
return (0, result_1.ok)("ngm_runtime_set_for_project", (0, operation_result_1.blocked)("write", "medium", safetyMessage, "ng-manager local server is unavailable; start ngm server or ngm ui before writing project runtime config", {
|
|
62
|
+
...(0, operation_result_1.controlledFields)("write", true, (0, operation_policy_1.requiredEnv)("write")),
|
|
63
|
+
localServer: serverCheck.availability,
|
|
64
|
+
project: { id: project.id, name: project.name, root: project.root },
|
|
65
|
+
oldRuntime,
|
|
66
|
+
newRuntime: nextRuntime,
|
|
67
|
+
}, error_codes_1.McpErrorCodes.LOCAL_SERVER_UNAVAILABLE));
|
|
68
|
+
}
|
|
69
|
+
const updatedProject = await serverCheck.server.updateProjectRuntime(project.id, nextRuntime);
|
|
70
|
+
const verifiedRuntime = await context.services.core.nodeRuntime.resolveRuntime(nextRuntime);
|
|
71
|
+
return (0, result_1.ok)("ngm_runtime_set_for_project", {
|
|
72
|
+
...preview,
|
|
73
|
+
...(0, operation_result_1.controlledFields)("write", true, (0, operation_policy_1.requiredEnv)("write")),
|
|
74
|
+
operation: (0, operation_result_1.operation)("executed", "write", "medium", safetyMessage),
|
|
75
|
+
controlPlane: "local-server",
|
|
76
|
+
localServer: serverCheck.availability,
|
|
77
|
+
project: {
|
|
78
|
+
id: updatedProject.id,
|
|
79
|
+
name: updatedProject.name,
|
|
80
|
+
root: updatedProject.root,
|
|
81
|
+
runtime: updatedProject.runtime,
|
|
82
|
+
nodeVersion: updatedProject.nodeVersion,
|
|
83
|
+
},
|
|
84
|
+
verifiedRuntime,
|
|
85
|
+
});
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
];
|
|
89
|
+
}
|
|
@@ -29,17 +29,27 @@ function runtimeConfigForProject(project) {
|
|
|
29
29
|
function runtimeTools() {
|
|
30
30
|
return [
|
|
31
31
|
{
|
|
32
|
-
name: "
|
|
32
|
+
name: "ngm_runtime_current",
|
|
33
|
+
description: "Read current Node version manager information known to ng-manager.",
|
|
34
|
+
riskLevel: "read",
|
|
35
|
+
inputSchema: zod_1.z.object({}).strict(),
|
|
36
|
+
async handler(_args, context) {
|
|
37
|
+
const current = await context.services.core.nodeVersion.getCurrentVersion();
|
|
38
|
+
return (0, result_1.ok)("ngm_runtime_current", current);
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
name: "ngm_runtime_list",
|
|
33
43
|
description: "List Node runtimes known to ng-manager.",
|
|
34
44
|
riskLevel: "read",
|
|
35
45
|
inputSchema: zod_1.z.object({}).strict(),
|
|
36
46
|
async handler(_args, context) {
|
|
37
47
|
const runtimes = await context.services.core.nodeRuntime.listRuntimes();
|
|
38
|
-
return (0, result_1.ok)("
|
|
48
|
+
return (0, result_1.ok)("ngm_runtime_list", runtimes);
|
|
39
49
|
},
|
|
40
50
|
},
|
|
41
51
|
{
|
|
42
|
-
name: "
|
|
52
|
+
name: "ngm_runtime_resolve_for_project",
|
|
43
53
|
description: "Resolve the Node runtime ng-manager would use for a project.",
|
|
44
54
|
riskLevel: "read",
|
|
45
55
|
inputSchema: project_tools_1.projectLocatorSchema,
|
|
@@ -47,7 +57,7 @@ function runtimeTools() {
|
|
|
47
57
|
const project = await (0, project_tools_1.resolveProject)(context, args);
|
|
48
58
|
const requestedRuntime = runtimeConfigForProject(project);
|
|
49
59
|
const resolvedRuntime = await context.services.core.nodeRuntime.resolveRuntime(requestedRuntime);
|
|
50
|
-
return (0, result_1.ok)("
|
|
60
|
+
return (0, result_1.ok)("ngm_runtime_resolve_for_project", {
|
|
51
61
|
project: {
|
|
52
62
|
id: project.id,
|
|
53
63
|
name: project.name,
|
|
@@ -61,5 +71,32 @@ function runtimeTools() {
|
|
|
61
71
|
});
|
|
62
72
|
},
|
|
63
73
|
},
|
|
74
|
+
{
|
|
75
|
+
name: "ngm_runtime_detect_requirement",
|
|
76
|
+
description: "Detect Node version requirements for a project path or registered ng-manager project.",
|
|
77
|
+
riskLevel: "read",
|
|
78
|
+
inputSchema: project_tools_1.projectLocatorSchema,
|
|
79
|
+
async handler(args, context) {
|
|
80
|
+
let projectPath = args.projectPath;
|
|
81
|
+
let project;
|
|
82
|
+
if (args.projectId) {
|
|
83
|
+
const resolvedProject = await (0, project_tools_1.resolveProject)(context, { projectId: args.projectId });
|
|
84
|
+
projectPath = resolvedProject.root;
|
|
85
|
+
project = {
|
|
86
|
+
id: resolvedProject.id,
|
|
87
|
+
name: resolvedProject.name,
|
|
88
|
+
root: resolvedProject.root,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
if (!projectPath) {
|
|
92
|
+
throw new Error("projectId or projectPath is required");
|
|
93
|
+
}
|
|
94
|
+
const requirement = await context.services.core.nodeVersion.detectProjectRequirement(projectPath);
|
|
95
|
+
return (0, result_1.ok)("ngm_runtime_detect_requirement", {
|
|
96
|
+
project,
|
|
97
|
+
requirement,
|
|
98
|
+
});
|
|
99
|
+
},
|
|
100
|
+
},
|
|
64
101
|
];
|
|
65
102
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { standardTools } from "./standard.tools";
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.standardTools = void 0;
|
|
4
|
+
var standard_tools_1 = require("./standard.tools");
|
|
5
|
+
Object.defineProperty(exports, "standardTools", { enumerable: true, get: function () { return standard_tools_1.standardTools; } });
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.standardTools = standardTools;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const result_1 = require("../../utils/result");
|
|
6
|
+
const project_files_1 = require("../../filesystem/project-files");
|
|
7
|
+
const operation_result_1 = require("../controlled/operation-result");
|
|
8
|
+
const operation_policy_1 = require("../controlled/operation-policy");
|
|
9
|
+
const frontend_standard_service_1 = require("../../standard/frontend-standard.service");
|
|
10
|
+
const projectSchema = zod_1.z.object({
|
|
11
|
+
projectId: zod_1.z.string().trim().min(1).optional(),
|
|
12
|
+
projectPath: zod_1.z.string().trim().min(1).optional(),
|
|
13
|
+
}).strict();
|
|
14
|
+
const initSchema = projectSchema.extend({
|
|
15
|
+
overwrite: zod_1.z.boolean().optional(),
|
|
16
|
+
confirm: zod_1.z.boolean().optional(),
|
|
17
|
+
dryRun: zod_1.z.boolean().optional(),
|
|
18
|
+
}).strict();
|
|
19
|
+
function standardTools() {
|
|
20
|
+
return [
|
|
21
|
+
{
|
|
22
|
+
name: "ngm_standard_get",
|
|
23
|
+
description: "Read the frontend standard config for a project, returning defaults when .ng-manager/frontend-standard.json does not exist.",
|
|
24
|
+
riskLevel: "read",
|
|
25
|
+
inputSchema: projectSchema,
|
|
26
|
+
async handler(args, context) {
|
|
27
|
+
const project = await (0, project_files_1.resolveProjectRoot)(context, args);
|
|
28
|
+
const loaded = await (0, frontend_standard_service_1.loadFrontendStandard)(project);
|
|
29
|
+
return (0, result_1.ok)("ngm_standard_get", {
|
|
30
|
+
project,
|
|
31
|
+
source: loaded.source,
|
|
32
|
+
path: (0, project_files_1.projectRelativePath)(project.projectRoot, loaded.path),
|
|
33
|
+
standard: loaded.standard,
|
|
34
|
+
});
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: "ngm_standard_init",
|
|
39
|
+
description: "Preview or create .ng-manager/frontend-standard.json for a project. Requires confirm=true and NGM_MCP_ALLOW_WRITE=true to write.",
|
|
40
|
+
riskLevel: "write",
|
|
41
|
+
allowPreviewWhenBlocked: true,
|
|
42
|
+
deferPolicyToHandler: true,
|
|
43
|
+
isConfirmed: operation_result_1.isConfirmed,
|
|
44
|
+
inputSchema: initSchema,
|
|
45
|
+
async handler(args, context) {
|
|
46
|
+
const project = await (0, project_files_1.resolveProjectRoot)(context, args);
|
|
47
|
+
const loaded = await (0, frontend_standard_service_1.loadFrontendStandard)(project);
|
|
48
|
+
const safetyMessage = "Create or replace project frontend standard configuration.";
|
|
49
|
+
const preview = {
|
|
50
|
+
operation: (0, operation_result_1.operation)("preview", "write", "low", safetyMessage),
|
|
51
|
+
project,
|
|
52
|
+
path: (0, project_files_1.projectRelativePath)(project.projectRoot, loaded.path),
|
|
53
|
+
standard: loaded.standard,
|
|
54
|
+
};
|
|
55
|
+
if (!(0, operation_result_1.isConfirmed)(args))
|
|
56
|
+
return (0, result_1.ok)("ngm_standard_init", preview);
|
|
57
|
+
const policyBlock = (0, operation_policy_1.requireWritePolicy)("low", safetyMessage);
|
|
58
|
+
if (policyBlock)
|
|
59
|
+
return (0, result_1.ok)("ngm_standard_init", policyBlock);
|
|
60
|
+
const result = await (0, frontend_standard_service_1.initFrontendStandard)(project, args.overwrite === true);
|
|
61
|
+
if (result.status === "blocked") {
|
|
62
|
+
return (0, result_1.ok)("ngm_standard_init", (0, operation_result_1.blocked)("write", "low", safetyMessage, result.reason ?? "frontend standard init was blocked", {
|
|
63
|
+
path: (0, project_files_1.projectRelativePath)(project.projectRoot, result.path),
|
|
64
|
+
}));
|
|
65
|
+
}
|
|
66
|
+
return (0, result_1.ok)("ngm_standard_init", {
|
|
67
|
+
...preview,
|
|
68
|
+
operation: (0, operation_result_1.operation)("executed", "write", "low", safetyMessage),
|
|
69
|
+
path: (0, project_files_1.projectRelativePath)(project.projectRoot, result.path),
|
|
70
|
+
changedFiles: result.changedFiles,
|
|
71
|
+
});
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: "ngm_standard_validate_project",
|
|
76
|
+
description: "Run lightweight frontend standard checks for Angular structure, component boundaries, and test naming.",
|
|
77
|
+
riskLevel: "read",
|
|
78
|
+
inputSchema: projectSchema,
|
|
79
|
+
async handler(args, context) {
|
|
80
|
+
const project = await (0, project_files_1.resolveProjectRoot)(context, args);
|
|
81
|
+
const loaded = await (0, frontend_standard_service_1.loadFrontendStandard)(project);
|
|
82
|
+
const result = await (0, frontend_standard_service_1.validateFrontendProject)(project, loaded.standard);
|
|
83
|
+
return (0, result_1.ok)("ngm_standard_validate_project", {
|
|
84
|
+
project,
|
|
85
|
+
standardSource: loaded.source,
|
|
86
|
+
...result,
|
|
87
|
+
});
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
];
|
|
91
|
+
}
|