devchain-cli 0.6.1 → 0.7.1
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/dist/drizzle/0024_review_tables.sql +71 -0
- package/dist/drizzle/0025_reviews_mode_and_nullable_shas.sql +80 -0
- package/dist/drizzle/0026_review_comments_edited_at.sql +2 -0
- package/dist/drizzle/meta/_journal.json +22 -1
- package/dist/server/common/errors/error-types.d.ts +3 -0
- package/dist/server/common/errors/error-types.js +7 -1
- package/dist/server/common/errors/error-types.js.map +1 -1
- package/dist/server/common/validation/path-validation.d.ts +11 -0
- package/dist/server/common/validation/path-validation.js +197 -0
- package/dist/server/common/validation/path-validation.js.map +1 -0
- package/dist/server/modules/chat/dtos/chat.dto.d.ts +13 -13
- package/dist/server/modules/core/core.module.js +3 -2
- package/dist/server/modules/core/core.module.js.map +1 -1
- package/dist/server/modules/core/services/preflight.service.d.ts +1 -3
- package/dist/server/modules/core/services/preflight.service.js +2 -28
- package/dist/server/modules/core/services/preflight.service.js.map +1 -1
- package/dist/server/modules/core/services/provider-mcp-ensure.service.d.ts +26 -0
- package/dist/server/modules/core/services/provider-mcp-ensure.service.js +224 -0
- package/dist/server/modules/core/services/provider-mcp-ensure.service.js.map +1 -0
- package/dist/server/modules/epics/controllers/epics.controller.d.ts +3 -2
- package/dist/server/modules/epics/controllers/epics.controller.js +16 -6
- package/dist/server/modules/epics/controllers/epics.controller.js.map +1 -1
- package/dist/server/modules/events/catalog/epic.created.d.ts +2 -2
- package/dist/server/modules/events/catalog/index.d.ts +340 -2
- package/dist/server/modules/events/catalog/index.js +12 -0
- package/dist/server/modules/events/catalog/index.js.map +1 -1
- package/dist/server/modules/events/catalog/review.comment.created.d.ts +69 -0
- package/dist/server/modules/events/catalog/review.comment.created.js +30 -0
- package/dist/server/modules/events/catalog/review.comment.created.js.map +1 -0
- package/dist/server/modules/events/catalog/review.comment.deleted.d.ts +30 -0
- package/dist/server/modules/events/catalog/review.comment.deleted.js +17 -0
- package/dist/server/modules/events/catalog/review.comment.deleted.js.map +1 -0
- package/dist/server/modules/events/catalog/review.comment.resolved.d.ts +30 -0
- package/dist/server/modules/events/catalog/review.comment.resolved.js +17 -0
- package/dist/server/modules/events/catalog/review.comment.resolved.js.map +1 -0
- package/dist/server/modules/events/catalog/review.comment.updated.d.ts +39 -0
- package/dist/server/modules/events/catalog/review.comment.updated.js +20 -0
- package/dist/server/modules/events/catalog/review.comment.updated.js.map +1 -0
- package/dist/server/modules/events/catalog/review.created.d.ts +90 -0
- package/dist/server/modules/events/catalog/review.created.js +40 -0
- package/dist/server/modules/events/catalog/review.created.js.map +1 -0
- package/dist/server/modules/events/catalog/review.updated.d.ts +110 -0
- package/dist/server/modules/events/catalog/review.updated.js +35 -0
- package/dist/server/modules/events/catalog/review.updated.js.map +1 -0
- package/dist/server/modules/events/subscribers/index.js +4 -0
- package/dist/server/modules/events/subscribers/index.js.map +1 -1
- package/dist/server/modules/events/subscribers/review-broadcaster.subscriber.d.ts +16 -0
- package/dist/server/modules/events/subscribers/review-broadcaster.subscriber.js +163 -0
- package/dist/server/modules/events/subscribers/review-broadcaster.subscriber.js.map +1 -0
- package/dist/server/modules/events/subscribers/review-comment-notifier.subscriber.d.ts +23 -0
- package/dist/server/modules/events/subscribers/review-comment-notifier.subscriber.js +217 -0
- package/dist/server/modules/events/subscribers/review-comment-notifier.subscriber.js.map +1 -0
- package/dist/server/modules/git/controllers/git.controller.d.ts +24 -0
- package/dist/server/modules/git/controllers/git.controller.js +230 -0
- package/dist/server/modules/git/controllers/git.controller.js.map +1 -0
- package/dist/server/modules/git/dtos/git.dto.d.ts +86 -0
- package/dist/server/modules/git/dtos/git.dto.js +36 -0
- package/dist/server/modules/git/dtos/git.dto.js.map +1 -0
- package/dist/server/modules/git/git.module.d.ts +2 -0
- package/dist/server/modules/git/git.module.js +25 -0
- package/dist/server/modules/git/git.module.js.map +1 -0
- package/dist/server/modules/git/services/git.service.d.ts +71 -0
- package/dist/server/modules/git/services/git.service.js +550 -0
- package/dist/server/modules/git/services/git.service.js.map +1 -0
- package/dist/server/modules/mcp/controllers/mcp-http.controller.js +17 -562
- package/dist/server/modules/mcp/controllers/mcp-http.controller.js.map +1 -1
- package/dist/server/modules/mcp/controllers/mcp-sdk.controller.js +9 -568
- package/dist/server/modules/mcp/controllers/mcp-sdk.controller.js.map +1 -1
- package/dist/server/modules/mcp/dtos/mcp.dto.d.ts +226 -36
- package/dist/server/modules/mcp/dtos/mcp.dto.js +158 -50
- package/dist/server/modules/mcp/dtos/mcp.dto.js.map +1 -1
- package/dist/server/modules/mcp/dtos/schema-registry.d.ts +7 -0
- package/dist/server/modules/mcp/dtos/schema-registry.js +56 -0
- package/dist/server/modules/mcp/dtos/schema-registry.js.map +1 -0
- package/dist/server/modules/mcp/mcp.module.js +2 -0
- package/dist/server/modules/mcp/mcp.module.js.map +1 -1
- package/dist/server/modules/mcp/services/mcp.service.d.ts +9 -1
- package/dist/server/modules/mcp/services/mcp.service.js +702 -33
- package/dist/server/modules/mcp/services/mcp.service.js.map +1 -1
- package/dist/server/modules/mcp/tool-definitions.d.ts +2438 -0
- package/dist/server/modules/mcp/tool-definitions.js +727 -0
- package/dist/server/modules/mcp/tool-definitions.js.map +1 -0
- package/dist/server/modules/mcp/utils/param-suggestion.d.ts +3 -0
- package/dist/server/modules/mcp/utils/param-suggestion.js +95 -0
- package/dist/server/modules/mcp/utils/param-suggestion.js.map +1 -0
- package/dist/server/modules/providers/controllers/providers.controller.d.ts +7 -6
- package/dist/server/modules/providers/controllers/providers.controller.js +12 -107
- package/dist/server/modules/providers/controllers/providers.controller.js.map +1 -1
- package/dist/server/modules/reviews/controllers/reviews.controller.d.ts +28 -0
- package/dist/server/modules/reviews/controllers/reviews.controller.js +369 -0
- package/dist/server/modules/reviews/controllers/reviews.controller.js.map +1 -0
- package/dist/server/modules/reviews/dtos/review.dto.d.ts +195 -0
- package/dist/server/modules/reviews/dtos/review.dto.js +92 -0
- package/dist/server/modules/reviews/dtos/review.dto.js.map +1 -0
- package/dist/server/modules/reviews/reviews.module.d.ts +2 -0
- package/dist/server/modules/reviews/reviews.module.js +27 -0
- package/dist/server/modules/reviews/reviews.module.js.map +1 -0
- package/dist/server/modules/reviews/services/reviews.service.d.ts +86 -0
- package/dist/server/modules/reviews/services/reviews.service.js +464 -0
- package/dist/server/modules/reviews/services/reviews.service.js.map +1 -0
- package/dist/server/modules/reviews/utils/notification-formatter.d.ts +12 -0
- package/dist/server/modules/reviews/utils/notification-formatter.js +60 -0
- package/dist/server/modules/reviews/utils/notification-formatter.js.map +1 -0
- package/dist/server/modules/sessions/services/sessions.service.d.ts +3 -1
- package/dist/server/modules/sessions/services/sessions.service.js +32 -2
- package/dist/server/modules/sessions/services/sessions.service.js.map +1 -1
- package/dist/server/modules/storage/db/schema.d.ts +697 -0
- package/dist/server/modules/storage/db/schema.js +71 -1
- package/dist/server/modules/storage/db/schema.js.map +1 -1
- package/dist/server/modules/storage/interfaces/storage.interface.d.ts +23 -1
- package/dist/server/modules/storage/interfaces/storage.interface.js.map +1 -1
- package/dist/server/modules/storage/local/local-storage.service.d.ts +15 -2
- package/dist/server/modules/storage/local/local-storage.service.js +396 -7
- package/dist/server/modules/storage/local/local-storage.service.js.map +1 -1
- package/dist/server/modules/storage/models/domain.models.d.ts +62 -0
- package/dist/server/templates/claude-claude-swe.json +148 -0
- package/dist/server/templates/claude-codex-advanced-swe.json +139 -0
- package/dist/server/templates/claude-codex-advanced.json +84 -84
- package/dist/server/templates/claude-opus.json +102 -101
- package/dist/server/templates/claude-swe-single.json +105 -0
- package/dist/server/templates/codex-claude-swe.json +148 -0
- package/dist/server/templates/simple-codex.json +74 -74
- package/dist/server/test-setup.js +45 -0
- package/dist/server/test-setup.js.map +1 -1
- package/dist/server/tsconfig.tsbuildinfo +1 -1
- package/dist/server/ui/assets/ReviewDetailPage-I54h-2L-.js +6 -0
- package/dist/server/ui/assets/ReviewsPage-B4ua5hiX.js +19 -0
- package/dist/server/ui/assets/index-CqcmnFBh.css +32 -0
- package/dist/server/ui/assets/index-JbUMpbg7.js +858 -0
- package/dist/server/ui/assets/useReviewSubscription-C0GEsiRw.js +83 -0
- package/dist/server/ui/assets/useReviewSubscription-T3uj2-aP.css +1 -0
- package/dist/server/ui/index.html +2 -2
- package/dist/templates/claude-claude-swe.json +148 -0
- package/dist/templates/claude-codex-advanced-swe.json +139 -0
- package/dist/templates/claude-codex-advanced.json +84 -84
- package/dist/templates/claude-opus.json +102 -101
- package/dist/templates/claude-swe-single.json +105 -0
- package/dist/templates/codex-claude-swe.json +148 -0
- package/dist/templates/simple-codex.json +74 -74
- package/package.json +15 -2
- package/prebuilds/node-pty/darwin-arm64/pty.node +0 -0
- package/prebuilds/node-pty/darwin-arm64/spawn-helper +0 -0
- package/prebuilds/node-pty/darwin-x64/pty.node +0 -0
- package/prebuilds/node-pty/darwin-x64/spawn-helper +0 -0
- package/prebuilds/node-pty/linux-arm64/pty.node +0 -0
- package/prebuilds/node-pty/linux-x64/pty.node +0 -0
- package/prebuilds/node-pty/win32-arm64/conpty/OpenConsole.exe +0 -0
- package/prebuilds/node-pty/win32-arm64/conpty/conpty.dll +0 -0
- package/prebuilds/node-pty/win32-arm64/conpty.node +0 -0
- package/prebuilds/node-pty/win32-arm64/conpty.pdb +0 -0
- package/prebuilds/node-pty/win32-arm64/conpty_console_list.node +0 -0
- package/prebuilds/node-pty/win32-arm64/conpty_console_list.pdb +0 -0
- package/prebuilds/node-pty/win32-arm64/pty.node +0 -0
- package/prebuilds/node-pty/win32-arm64/pty.pdb +0 -0
- package/prebuilds/node-pty/win32-arm64/winpty-agent.exe +0 -0
- package/prebuilds/node-pty/win32-arm64/winpty-agent.pdb +0 -0
- package/prebuilds/node-pty/win32-arm64/winpty.dll +0 -0
- package/prebuilds/node-pty/win32-arm64/winpty.pdb +0 -0
- package/prebuilds/node-pty/win32-x64/conpty/OpenConsole.exe +0 -0
- package/prebuilds/node-pty/win32-x64/conpty/conpty.dll +0 -0
- package/prebuilds/node-pty/win32-x64/conpty.node +0 -0
- package/prebuilds/node-pty/win32-x64/conpty.pdb +0 -0
- package/prebuilds/node-pty/win32-x64/conpty_console_list.node +0 -0
- package/prebuilds/node-pty/win32-x64/conpty_console_list.pdb +0 -0
- package/prebuilds/node-pty/win32-x64/pty.node +0 -0
- package/prebuilds/node-pty/win32-x64/pty.pdb +0 -0
- package/prebuilds/node-pty/win32-x64/winpty-agent.exe +0 -0
- package/prebuilds/node-pty/win32-x64/winpty-agent.pdb +0 -0
- package/prebuilds/node-pty/win32-x64/winpty.dll +0 -0
- package/prebuilds/node-pty/win32-x64/winpty.pdb +0 -0
- package/scripts/postinstall.js +51 -1
- package/dist/server/ui/assets/index-BoDZOB7c.css +0 -32
- package/dist/server/ui/assets/index-hB0e02VB.js +0 -735
|
@@ -1,10 +1,43 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
2
18
|
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
19
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
20
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
21
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
22
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
23
|
};
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
8
41
|
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
42
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
43
|
};
|
|
@@ -23,12 +56,16 @@ const tmux_service_1 = require("../../terminal/services/tmux.service");
|
|
|
23
56
|
const epics_service_1 = require("../../epics/services/epics.service");
|
|
24
57
|
const settings_service_1 = require("../../settings/services/settings.service");
|
|
25
58
|
const guests_service_1 = require("../../guests/services/guests.service");
|
|
59
|
+
const reviews_service_1 = require("../../reviews/services/reviews.service");
|
|
26
60
|
const logger_1 = require("../../../common/logging/logger");
|
|
61
|
+
const schema_registry_1 = require("../dtos/schema-registry");
|
|
27
62
|
const mcp_dto_1 = require("../dtos/mcp.dto");
|
|
28
63
|
const instructions_resolver_1 = require("./instructions-resolver");
|
|
29
64
|
const error_types_1 = require("../../../common/errors/error-types");
|
|
65
|
+
const path_validation_1 = require("../../../common/validation/path-validation");
|
|
30
66
|
const common_2 = require("@nestjs/common");
|
|
31
67
|
const zod_1 = require("zod");
|
|
68
|
+
const param_suggestion_1 = require("../utils/param-suggestion");
|
|
32
69
|
const logger = (0, logger_1.createLogger)('McpService');
|
|
33
70
|
function getActorFromContext(ctx) {
|
|
34
71
|
if (ctx.type === 'agent') {
|
|
@@ -58,7 +95,7 @@ function redactParams(params) {
|
|
|
58
95
|
return params;
|
|
59
96
|
}
|
|
60
97
|
let McpService = class McpService {
|
|
61
|
-
constructor(storage, chatService, sessionsService, messagePoolService, terminalGateway, tmuxService, epicsService, settingsService, guestsService) {
|
|
98
|
+
constructor(storage, chatService, sessionsService, messagePoolService, terminalGateway, tmuxService, epicsService, settingsService, guestsService, reviewsService) {
|
|
62
99
|
this.storage = storage;
|
|
63
100
|
this.chatService = chatService;
|
|
64
101
|
this.sessionsService = sessionsService;
|
|
@@ -68,6 +105,7 @@ let McpService = class McpService {
|
|
|
68
105
|
this.epicsService = epicsService;
|
|
69
106
|
this.settingsService = settingsService;
|
|
70
107
|
this.guestsService = guestsService;
|
|
108
|
+
this.reviewsService = reviewsService;
|
|
71
109
|
this.DEFAULT_INLINE_MAX_BYTES = 64 * 1024;
|
|
72
110
|
logger.info('McpService initialized');
|
|
73
111
|
this.featureFlags = this.storage.getFeatureFlags();
|
|
@@ -100,70 +138,84 @@ let McpService = class McpService {
|
|
|
100
138
|
return { id: matches[0].id, name: matches[0].name };
|
|
101
139
|
}
|
|
102
140
|
async handleToolCall(tool, params) {
|
|
141
|
+
const normalizedParams = params ?? {};
|
|
142
|
+
const normalizedTool = tool.replace(/[.\-/]/g, '_');
|
|
103
143
|
try {
|
|
104
|
-
|
|
105
|
-
logger.info({ tool: normalizedTool, originalTool: tool, params: redactParams(params) }, 'Handling MCP tool call');
|
|
144
|
+
logger.info({ tool: normalizedTool, originalTool: tool, params: redactParams(normalizedParams) }, 'Handling MCP tool call');
|
|
106
145
|
switch (normalizedTool) {
|
|
107
146
|
case 'devchain_create_record':
|
|
108
|
-
return await this.createRecord(
|
|
147
|
+
return await this.createRecord(normalizedParams);
|
|
109
148
|
case 'devchain_update_record':
|
|
110
|
-
return await this.updateRecord(
|
|
149
|
+
return await this.updateRecord(normalizedParams);
|
|
111
150
|
case 'devchain_get_record':
|
|
112
|
-
return await this.getRecord(
|
|
151
|
+
return await this.getRecord(normalizedParams);
|
|
113
152
|
case 'devchain_list_records':
|
|
114
|
-
return await this.listRecords(
|
|
153
|
+
return await this.listRecords(normalizedParams);
|
|
115
154
|
case 'devchain_add_tags':
|
|
116
|
-
return await this.addTags(
|
|
155
|
+
return await this.addTags(normalizedParams);
|
|
117
156
|
case 'devchain_remove_tags':
|
|
118
|
-
return await this.removeTags(
|
|
157
|
+
return await this.removeTags(normalizedParams);
|
|
119
158
|
case 'devchain_list_documents':
|
|
120
|
-
return await this.listDocuments(
|
|
159
|
+
return await this.listDocuments(normalizedParams);
|
|
121
160
|
case 'devchain_get_document':
|
|
122
|
-
return await this.getDocument(
|
|
161
|
+
return await this.getDocument(normalizedParams);
|
|
123
162
|
case 'devchain_create_document':
|
|
124
|
-
return await this.createDocument(
|
|
163
|
+
return await this.createDocument(normalizedParams);
|
|
125
164
|
case 'devchain_update_document':
|
|
126
|
-
return await this.updateDocument(
|
|
165
|
+
return await this.updateDocument(normalizedParams);
|
|
127
166
|
case 'devchain_list_prompts':
|
|
128
|
-
return await this.listPrompts(
|
|
167
|
+
return await this.listPrompts(normalizedParams);
|
|
129
168
|
case 'devchain_get_prompt':
|
|
130
|
-
return await this.getPrompt(
|
|
169
|
+
return await this.getPrompt(normalizedParams);
|
|
131
170
|
case 'devchain_list_agents':
|
|
132
|
-
return await this.listAgents(
|
|
171
|
+
return await this.listAgents(normalizedParams);
|
|
133
172
|
case 'devchain_get_agent_by_name':
|
|
134
|
-
return await this.getAgentByName(
|
|
173
|
+
return await this.getAgentByName(normalizedParams);
|
|
135
174
|
case 'devchain_list_statuses':
|
|
136
|
-
return await this.listStatuses(
|
|
175
|
+
return await this.listStatuses(normalizedParams);
|
|
137
176
|
case 'devchain_list_epics':
|
|
138
|
-
return await this.listEpics(
|
|
177
|
+
return await this.listEpics(normalizedParams);
|
|
139
178
|
case 'devchain_list_assigned_epics_tasks':
|
|
140
|
-
return await this.listAssignedEpicsTasks(
|
|
179
|
+
return await this.listAssignedEpicsTasks(normalizedParams);
|
|
141
180
|
case 'devchain_create_epic':
|
|
142
|
-
return await this.createEpic(
|
|
181
|
+
return await this.createEpic(normalizedParams);
|
|
143
182
|
case 'devchain_get_epic_by_id':
|
|
144
|
-
return await this.getEpicById(
|
|
183
|
+
return await this.getEpicById(normalizedParams);
|
|
145
184
|
case 'devchain_add_epic_comment':
|
|
146
|
-
return await this.addEpicComment(
|
|
185
|
+
return await this.addEpicComment(normalizedParams);
|
|
147
186
|
case 'devchain_update_epic':
|
|
148
|
-
return await this.updateEpic(
|
|
187
|
+
return await this.updateEpic(normalizedParams);
|
|
149
188
|
case 'notifications_initialized':
|
|
150
189
|
return { success: true, data: { acknowledged: true } };
|
|
151
190
|
case 'devchain_send_message':
|
|
152
|
-
return await this.sendMessage(
|
|
191
|
+
return await this.sendMessage(normalizedParams);
|
|
153
192
|
case 'devchain_chat_ack':
|
|
154
|
-
return await this.chatAck(
|
|
193
|
+
return await this.chatAck(normalizedParams);
|
|
155
194
|
case 'devchain_chat_list_members':
|
|
156
|
-
return await this.chatListMembers(
|
|
195
|
+
return await this.chatListMembers(normalizedParams);
|
|
157
196
|
case 'devchain_chat_read_history':
|
|
158
|
-
return await this.chatReadHistory(
|
|
197
|
+
return await this.chatReadHistory(normalizedParams);
|
|
159
198
|
case 'devchain_activity_start':
|
|
160
|
-
return await this.activityStart(
|
|
199
|
+
return await this.activityStart(normalizedParams);
|
|
161
200
|
case 'devchain_activity_finish':
|
|
162
|
-
return await this.activityFinish(
|
|
201
|
+
return await this.activityFinish(normalizedParams);
|
|
163
202
|
case 'devchain_list_sessions':
|
|
203
|
+
schema_registry_1.ListSessionsParamsSchema.parse(normalizedParams);
|
|
164
204
|
return await this.listSessions();
|
|
165
205
|
case 'devchain_register_guest':
|
|
166
|
-
return await this.registerGuest(
|
|
206
|
+
return await this.registerGuest(normalizedParams);
|
|
207
|
+
case 'devchain_list_reviews':
|
|
208
|
+
return await this.listReviews(normalizedParams);
|
|
209
|
+
case 'devchain_get_review':
|
|
210
|
+
return await this.getReview(normalizedParams);
|
|
211
|
+
case 'devchain_get_review_comments':
|
|
212
|
+
return await this.getReviewComments(normalizedParams);
|
|
213
|
+
case 'devchain_reply_comment':
|
|
214
|
+
return await this.replyComment(normalizedParams);
|
|
215
|
+
case 'devchain_resolve_comment':
|
|
216
|
+
return await this.resolveComment(normalizedParams);
|
|
217
|
+
case 'devchain_apply_suggestion':
|
|
218
|
+
return await this.applySuggestion(normalizedParams);
|
|
167
219
|
default:
|
|
168
220
|
logger.warn({ tool: normalizedTool }, 'Unknown MCP tool');
|
|
169
221
|
return {
|
|
@@ -178,12 +230,27 @@ let McpService = class McpService {
|
|
|
178
230
|
catch (error) {
|
|
179
231
|
logger.error({ tool, error }, 'MCP tool call failed');
|
|
180
232
|
if (error instanceof zod_1.ZodError) {
|
|
233
|
+
const suggestions = [];
|
|
234
|
+
for (const issue of error.issues) {
|
|
235
|
+
if (issue.code === 'unrecognized_keys') {
|
|
236
|
+
const unknownKeys = issue.keys;
|
|
237
|
+
for (const key of unknownKeys) {
|
|
238
|
+
const suggestion = (0, param_suggestion_1.suggestNestedPath)(key, normalizedTool);
|
|
239
|
+
if (suggestion) {
|
|
240
|
+
suggestions.push(suggestion);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
181
245
|
return {
|
|
182
246
|
success: false,
|
|
183
247
|
error: {
|
|
184
248
|
code: 'VALIDATION_ERROR',
|
|
185
249
|
message: 'Invalid parameters supplied to MCP tool.',
|
|
186
|
-
data: {
|
|
250
|
+
data: {
|
|
251
|
+
issues: error.issues,
|
|
252
|
+
...(suggestions.length > 0 && { suggestions }),
|
|
253
|
+
},
|
|
187
254
|
},
|
|
188
255
|
};
|
|
189
256
|
}
|
|
@@ -2637,6 +2704,606 @@ let McpService = class McpService {
|
|
|
2637
2704
|
.replace(/[^a-z0-9]+/g, '-')
|
|
2638
2705
|
.replace(/(^-|-$)/g, '');
|
|
2639
2706
|
}
|
|
2707
|
+
async listReviews(params) {
|
|
2708
|
+
const validated = mcp_dto_1.ListReviewsParamsSchema.parse(params);
|
|
2709
|
+
const ctx = await this.resolveSessionContext(validated.sessionId);
|
|
2710
|
+
if (!ctx.success)
|
|
2711
|
+
return ctx;
|
|
2712
|
+
const { project } = ctx.data;
|
|
2713
|
+
if (!project) {
|
|
2714
|
+
return {
|
|
2715
|
+
success: false,
|
|
2716
|
+
error: {
|
|
2717
|
+
code: 'PROJECT_NOT_FOUND',
|
|
2718
|
+
message: 'No project associated with this session',
|
|
2719
|
+
},
|
|
2720
|
+
};
|
|
2721
|
+
}
|
|
2722
|
+
if (!this.reviewsService) {
|
|
2723
|
+
return {
|
|
2724
|
+
success: false,
|
|
2725
|
+
error: {
|
|
2726
|
+
code: 'SERVICE_UNAVAILABLE',
|
|
2727
|
+
message: 'ReviewsService is not available',
|
|
2728
|
+
},
|
|
2729
|
+
};
|
|
2730
|
+
}
|
|
2731
|
+
const result = await this.reviewsService.listReviews(project.id, {
|
|
2732
|
+
status: validated.status,
|
|
2733
|
+
epicId: validated.epicId,
|
|
2734
|
+
limit: validated.limit ?? 100,
|
|
2735
|
+
offset: validated.offset ?? 0,
|
|
2736
|
+
});
|
|
2737
|
+
const reviews = result.items.map((review) => ({
|
|
2738
|
+
id: review.id,
|
|
2739
|
+
title: review.title,
|
|
2740
|
+
description: review.description,
|
|
2741
|
+
status: review.status,
|
|
2742
|
+
baseRef: review.baseRef,
|
|
2743
|
+
headRef: review.headRef,
|
|
2744
|
+
baseSha: review.baseSha,
|
|
2745
|
+
headSha: review.headSha,
|
|
2746
|
+
epicId: review.epicId,
|
|
2747
|
+
createdBy: review.createdBy,
|
|
2748
|
+
createdByAgentId: review.createdByAgentId,
|
|
2749
|
+
version: review.version,
|
|
2750
|
+
commentCount: review.commentCount,
|
|
2751
|
+
createdAt: review.createdAt,
|
|
2752
|
+
updatedAt: review.updatedAt,
|
|
2753
|
+
}));
|
|
2754
|
+
const response = {
|
|
2755
|
+
reviews,
|
|
2756
|
+
total: result.total,
|
|
2757
|
+
limit: result.limit,
|
|
2758
|
+
offset: result.offset,
|
|
2759
|
+
};
|
|
2760
|
+
return { success: true, data: response };
|
|
2761
|
+
}
|
|
2762
|
+
async getReview(params) {
|
|
2763
|
+
const validated = mcp_dto_1.GetReviewParamsSchema.parse(params);
|
|
2764
|
+
const ctx = await this.resolveSessionContext(validated.sessionId);
|
|
2765
|
+
if (!ctx.success)
|
|
2766
|
+
return ctx;
|
|
2767
|
+
const { project } = ctx.data;
|
|
2768
|
+
if (!project) {
|
|
2769
|
+
return {
|
|
2770
|
+
success: false,
|
|
2771
|
+
error: {
|
|
2772
|
+
code: 'PROJECT_NOT_FOUND',
|
|
2773
|
+
message: 'No project associated with this session',
|
|
2774
|
+
},
|
|
2775
|
+
};
|
|
2776
|
+
}
|
|
2777
|
+
if (!this.reviewsService) {
|
|
2778
|
+
return {
|
|
2779
|
+
success: false,
|
|
2780
|
+
error: {
|
|
2781
|
+
code: 'SERVICE_UNAVAILABLE',
|
|
2782
|
+
message: 'ReviewsService is not available',
|
|
2783
|
+
},
|
|
2784
|
+
};
|
|
2785
|
+
}
|
|
2786
|
+
try {
|
|
2787
|
+
const reviewWithFiles = await this.reviewsService.getReview(validated.reviewId);
|
|
2788
|
+
if (reviewWithFiles.projectId !== project.id) {
|
|
2789
|
+
return {
|
|
2790
|
+
success: false,
|
|
2791
|
+
error: {
|
|
2792
|
+
code: 'REVIEW_NOT_FOUND',
|
|
2793
|
+
message: `Review ${validated.reviewId} does not belong to this project`,
|
|
2794
|
+
},
|
|
2795
|
+
};
|
|
2796
|
+
}
|
|
2797
|
+
const commentsResult = await this.reviewsService.listComments(validated.reviewId, {
|
|
2798
|
+
limit: 500,
|
|
2799
|
+
});
|
|
2800
|
+
const agentIds = new Set();
|
|
2801
|
+
for (const comment of commentsResult.items) {
|
|
2802
|
+
if (comment.authorAgentId)
|
|
2803
|
+
agentIds.add(comment.authorAgentId);
|
|
2804
|
+
}
|
|
2805
|
+
const agentNameById = new Map();
|
|
2806
|
+
for (const agentId of agentIds) {
|
|
2807
|
+
try {
|
|
2808
|
+
const agent = await this.storage.getAgent(agentId);
|
|
2809
|
+
agentNameById.set(agentId, agent.name);
|
|
2810
|
+
}
|
|
2811
|
+
catch {
|
|
2812
|
+
}
|
|
2813
|
+
}
|
|
2814
|
+
const comments = commentsResult.items.map((comment) => ({
|
|
2815
|
+
id: comment.id,
|
|
2816
|
+
filePath: comment.filePath,
|
|
2817
|
+
lineStart: comment.lineStart,
|
|
2818
|
+
lineEnd: comment.lineEnd,
|
|
2819
|
+
side: comment.side,
|
|
2820
|
+
content: comment.content,
|
|
2821
|
+
commentType: comment.commentType,
|
|
2822
|
+
status: comment.status,
|
|
2823
|
+
authorType: comment.authorType,
|
|
2824
|
+
authorAgentId: comment.authorAgentId,
|
|
2825
|
+
authorAgentName: comment.authorAgentId
|
|
2826
|
+
? agentNameById.get(comment.authorAgentId)
|
|
2827
|
+
: undefined,
|
|
2828
|
+
parentId: comment.parentId,
|
|
2829
|
+
version: comment.version,
|
|
2830
|
+
createdAt: comment.createdAt,
|
|
2831
|
+
updatedAt: comment.updatedAt,
|
|
2832
|
+
}));
|
|
2833
|
+
const changedFiles = (reviewWithFiles.changedFiles ?? []).map((file) => ({
|
|
2834
|
+
path: file.path,
|
|
2835
|
+
status: file.status,
|
|
2836
|
+
additions: file.additions,
|
|
2837
|
+
deletions: file.deletions,
|
|
2838
|
+
oldPath: file.oldPath,
|
|
2839
|
+
}));
|
|
2840
|
+
const response = {
|
|
2841
|
+
review: {
|
|
2842
|
+
id: reviewWithFiles.id,
|
|
2843
|
+
title: reviewWithFiles.title,
|
|
2844
|
+
description: reviewWithFiles.description,
|
|
2845
|
+
status: reviewWithFiles.status,
|
|
2846
|
+
baseRef: reviewWithFiles.baseRef,
|
|
2847
|
+
headRef: reviewWithFiles.headRef,
|
|
2848
|
+
baseSha: reviewWithFiles.baseSha,
|
|
2849
|
+
headSha: reviewWithFiles.headSha,
|
|
2850
|
+
epicId: reviewWithFiles.epicId,
|
|
2851
|
+
createdBy: reviewWithFiles.createdBy,
|
|
2852
|
+
createdByAgentId: reviewWithFiles.createdByAgentId,
|
|
2853
|
+
version: reviewWithFiles.version,
|
|
2854
|
+
createdAt: reviewWithFiles.createdAt,
|
|
2855
|
+
updatedAt: reviewWithFiles.updatedAt,
|
|
2856
|
+
},
|
|
2857
|
+
changedFiles,
|
|
2858
|
+
comments,
|
|
2859
|
+
};
|
|
2860
|
+
return { success: true, data: response };
|
|
2861
|
+
}
|
|
2862
|
+
catch (error) {
|
|
2863
|
+
if (error instanceof error_types_1.NotFoundError) {
|
|
2864
|
+
return {
|
|
2865
|
+
success: false,
|
|
2866
|
+
error: {
|
|
2867
|
+
code: 'REVIEW_NOT_FOUND',
|
|
2868
|
+
message: `Review ${validated.reviewId} was not found`,
|
|
2869
|
+
},
|
|
2870
|
+
};
|
|
2871
|
+
}
|
|
2872
|
+
throw error;
|
|
2873
|
+
}
|
|
2874
|
+
}
|
|
2875
|
+
async getReviewComments(params) {
|
|
2876
|
+
const validated = mcp_dto_1.GetReviewCommentsParamsSchema.parse(params);
|
|
2877
|
+
const ctx = await this.resolveSessionContext(validated.sessionId);
|
|
2878
|
+
if (!ctx.success)
|
|
2879
|
+
return ctx;
|
|
2880
|
+
const { project } = ctx.data;
|
|
2881
|
+
if (!project) {
|
|
2882
|
+
return {
|
|
2883
|
+
success: false,
|
|
2884
|
+
error: {
|
|
2885
|
+
code: 'PROJECT_NOT_FOUND',
|
|
2886
|
+
message: 'No project associated with this session',
|
|
2887
|
+
},
|
|
2888
|
+
};
|
|
2889
|
+
}
|
|
2890
|
+
if (!this.reviewsService) {
|
|
2891
|
+
return {
|
|
2892
|
+
success: false,
|
|
2893
|
+
error: {
|
|
2894
|
+
code: 'SERVICE_UNAVAILABLE',
|
|
2895
|
+
message: 'ReviewsService is not available',
|
|
2896
|
+
},
|
|
2897
|
+
};
|
|
2898
|
+
}
|
|
2899
|
+
try {
|
|
2900
|
+
const review = await this.storage.getReview(validated.reviewId);
|
|
2901
|
+
if (review.projectId !== project.id) {
|
|
2902
|
+
return {
|
|
2903
|
+
success: false,
|
|
2904
|
+
error: {
|
|
2905
|
+
code: 'REVIEW_NOT_FOUND',
|
|
2906
|
+
message: `Review ${validated.reviewId} does not belong to this project`,
|
|
2907
|
+
},
|
|
2908
|
+
};
|
|
2909
|
+
}
|
|
2910
|
+
const result = await this.reviewsService.listComments(validated.reviewId, {
|
|
2911
|
+
status: validated.status,
|
|
2912
|
+
filePath: validated.filePath,
|
|
2913
|
+
limit: validated.limit ?? 100,
|
|
2914
|
+
offset: validated.offset ?? 0,
|
|
2915
|
+
});
|
|
2916
|
+
const agentIds = new Set();
|
|
2917
|
+
for (const comment of result.items) {
|
|
2918
|
+
if (comment.authorAgentId)
|
|
2919
|
+
agentIds.add(comment.authorAgentId);
|
|
2920
|
+
}
|
|
2921
|
+
const agentNameById = new Map();
|
|
2922
|
+
for (const agentId of agentIds) {
|
|
2923
|
+
try {
|
|
2924
|
+
const agent = await this.storage.getAgent(agentId);
|
|
2925
|
+
agentNameById.set(agentId, agent.name);
|
|
2926
|
+
}
|
|
2927
|
+
catch {
|
|
2928
|
+
}
|
|
2929
|
+
}
|
|
2930
|
+
const comments = result.items.map((comment) => ({
|
|
2931
|
+
id: comment.id,
|
|
2932
|
+
filePath: comment.filePath,
|
|
2933
|
+
lineStart: comment.lineStart,
|
|
2934
|
+
lineEnd: comment.lineEnd,
|
|
2935
|
+
side: comment.side,
|
|
2936
|
+
content: comment.content,
|
|
2937
|
+
commentType: comment.commentType,
|
|
2938
|
+
status: comment.status,
|
|
2939
|
+
authorType: comment.authorType,
|
|
2940
|
+
authorAgentId: comment.authorAgentId,
|
|
2941
|
+
authorAgentName: comment.authorAgentId
|
|
2942
|
+
? agentNameById.get(comment.authorAgentId)
|
|
2943
|
+
: undefined,
|
|
2944
|
+
parentId: comment.parentId,
|
|
2945
|
+
version: comment.version,
|
|
2946
|
+
createdAt: comment.createdAt,
|
|
2947
|
+
updatedAt: comment.updatedAt,
|
|
2948
|
+
}));
|
|
2949
|
+
const response = {
|
|
2950
|
+
comments,
|
|
2951
|
+
total: result.total,
|
|
2952
|
+
limit: result.limit,
|
|
2953
|
+
offset: result.offset,
|
|
2954
|
+
};
|
|
2955
|
+
return { success: true, data: response };
|
|
2956
|
+
}
|
|
2957
|
+
catch (error) {
|
|
2958
|
+
if (error instanceof error_types_1.NotFoundError) {
|
|
2959
|
+
return {
|
|
2960
|
+
success: false,
|
|
2961
|
+
error: {
|
|
2962
|
+
code: 'REVIEW_NOT_FOUND',
|
|
2963
|
+
message: `Review ${validated.reviewId} was not found`,
|
|
2964
|
+
},
|
|
2965
|
+
};
|
|
2966
|
+
}
|
|
2967
|
+
throw error;
|
|
2968
|
+
}
|
|
2969
|
+
}
|
|
2970
|
+
async replyComment(params) {
|
|
2971
|
+
const validated = mcp_dto_1.ReplyCommentParamsSchema.parse(params);
|
|
2972
|
+
const ctx = await this.resolveSessionContext(validated.sessionId);
|
|
2973
|
+
if (!ctx.success)
|
|
2974
|
+
return ctx;
|
|
2975
|
+
const { project } = ctx.data;
|
|
2976
|
+
const actor = getActorFromContext(ctx.data);
|
|
2977
|
+
if (!project) {
|
|
2978
|
+
return {
|
|
2979
|
+
success: false,
|
|
2980
|
+
error: {
|
|
2981
|
+
code: 'PROJECT_NOT_FOUND',
|
|
2982
|
+
message: 'No project associated with this session',
|
|
2983
|
+
},
|
|
2984
|
+
};
|
|
2985
|
+
}
|
|
2986
|
+
if (!this.reviewsService) {
|
|
2987
|
+
return {
|
|
2988
|
+
success: false,
|
|
2989
|
+
error: {
|
|
2990
|
+
code: 'SERVICE_UNAVAILABLE',
|
|
2991
|
+
message: 'ReviewsService is not available',
|
|
2992
|
+
},
|
|
2993
|
+
};
|
|
2994
|
+
}
|
|
2995
|
+
try {
|
|
2996
|
+
const review = await this.storage.getReview(validated.reviewId);
|
|
2997
|
+
if (review.projectId !== project.id) {
|
|
2998
|
+
return {
|
|
2999
|
+
success: false,
|
|
3000
|
+
error: {
|
|
3001
|
+
code: 'REVIEW_NOT_FOUND',
|
|
3002
|
+
message: `Review ${validated.reviewId} does not belong to this project`,
|
|
3003
|
+
},
|
|
3004
|
+
};
|
|
3005
|
+
}
|
|
3006
|
+
const comment = await this.reviewsService.createComment(validated.reviewId, {
|
|
3007
|
+
parentId: validated.parentCommentId,
|
|
3008
|
+
content: validated.content,
|
|
3009
|
+
filePath: validated.filePath,
|
|
3010
|
+
lineStart: validated.lineStart,
|
|
3011
|
+
lineEnd: validated.lineEnd,
|
|
3012
|
+
commentType: validated.commentType ?? 'comment',
|
|
3013
|
+
authorType: 'agent',
|
|
3014
|
+
authorAgentId: actor?.id,
|
|
3015
|
+
targetAgentIds: validated.targetAgentIds,
|
|
3016
|
+
});
|
|
3017
|
+
const response = {
|
|
3018
|
+
comment: {
|
|
3019
|
+
id: comment.id,
|
|
3020
|
+
filePath: comment.filePath,
|
|
3021
|
+
lineStart: comment.lineStart,
|
|
3022
|
+
lineEnd: comment.lineEnd,
|
|
3023
|
+
side: comment.side,
|
|
3024
|
+
content: comment.content,
|
|
3025
|
+
commentType: comment.commentType,
|
|
3026
|
+
status: comment.status,
|
|
3027
|
+
authorType: comment.authorType,
|
|
3028
|
+
authorAgentId: comment.authorAgentId,
|
|
3029
|
+
authorAgentName: actor?.name,
|
|
3030
|
+
parentId: comment.parentId,
|
|
3031
|
+
version: comment.version,
|
|
3032
|
+
createdAt: comment.createdAt,
|
|
3033
|
+
updatedAt: comment.updatedAt,
|
|
3034
|
+
},
|
|
3035
|
+
};
|
|
3036
|
+
return { success: true, data: response };
|
|
3037
|
+
}
|
|
3038
|
+
catch (error) {
|
|
3039
|
+
if (error instanceof error_types_1.NotFoundError) {
|
|
3040
|
+
return {
|
|
3041
|
+
success: false,
|
|
3042
|
+
error: {
|
|
3043
|
+
code: 'REVIEW_NOT_FOUND',
|
|
3044
|
+
message: `Review ${validated.reviewId} was not found`,
|
|
3045
|
+
},
|
|
3046
|
+
};
|
|
3047
|
+
}
|
|
3048
|
+
throw error;
|
|
3049
|
+
}
|
|
3050
|
+
}
|
|
3051
|
+
async resolveComment(params) {
|
|
3052
|
+
const validated = mcp_dto_1.ResolveCommentParamsSchema.parse(params);
|
|
3053
|
+
const ctx = await this.resolveSessionContext(validated.sessionId);
|
|
3054
|
+
if (!ctx.success)
|
|
3055
|
+
return ctx;
|
|
3056
|
+
const { project } = ctx.data;
|
|
3057
|
+
if (!project) {
|
|
3058
|
+
return {
|
|
3059
|
+
success: false,
|
|
3060
|
+
error: {
|
|
3061
|
+
code: 'PROJECT_NOT_FOUND',
|
|
3062
|
+
message: 'No project associated with this session',
|
|
3063
|
+
},
|
|
3064
|
+
};
|
|
3065
|
+
}
|
|
3066
|
+
if (!this.reviewsService) {
|
|
3067
|
+
return {
|
|
3068
|
+
success: false,
|
|
3069
|
+
error: {
|
|
3070
|
+
code: 'SERVICE_UNAVAILABLE',
|
|
3071
|
+
message: 'ReviewsService is not available',
|
|
3072
|
+
},
|
|
3073
|
+
};
|
|
3074
|
+
}
|
|
3075
|
+
try {
|
|
3076
|
+
const comment = await this.storage.getReviewComment(validated.commentId);
|
|
3077
|
+
const review = await this.storage.getReview(comment.reviewId);
|
|
3078
|
+
if (review.projectId !== project.id) {
|
|
3079
|
+
return {
|
|
3080
|
+
success: false,
|
|
3081
|
+
error: {
|
|
3082
|
+
code: 'COMMENT_NOT_FOUND',
|
|
3083
|
+
message: `Comment ${validated.commentId} does not belong to this project`,
|
|
3084
|
+
},
|
|
3085
|
+
};
|
|
3086
|
+
}
|
|
3087
|
+
const updatedComment = await this.reviewsService.resolveComment(comment.reviewId, validated.commentId, validated.resolution, validated.version);
|
|
3088
|
+
let authorAgentName;
|
|
3089
|
+
if (updatedComment.authorAgentId) {
|
|
3090
|
+
try {
|
|
3091
|
+
const agent = await this.storage.getAgent(updatedComment.authorAgentId);
|
|
3092
|
+
authorAgentName = agent.name;
|
|
3093
|
+
}
|
|
3094
|
+
catch {
|
|
3095
|
+
}
|
|
3096
|
+
}
|
|
3097
|
+
const response = {
|
|
3098
|
+
comment: {
|
|
3099
|
+
id: updatedComment.id,
|
|
3100
|
+
filePath: updatedComment.filePath,
|
|
3101
|
+
lineStart: updatedComment.lineStart,
|
|
3102
|
+
lineEnd: updatedComment.lineEnd,
|
|
3103
|
+
side: updatedComment.side,
|
|
3104
|
+
content: updatedComment.content,
|
|
3105
|
+
commentType: updatedComment.commentType,
|
|
3106
|
+
status: updatedComment.status,
|
|
3107
|
+
authorType: updatedComment.authorType,
|
|
3108
|
+
authorAgentId: updatedComment.authorAgentId,
|
|
3109
|
+
authorAgentName,
|
|
3110
|
+
parentId: updatedComment.parentId,
|
|
3111
|
+
version: updatedComment.version,
|
|
3112
|
+
createdAt: updatedComment.createdAt,
|
|
3113
|
+
updatedAt: updatedComment.updatedAt,
|
|
3114
|
+
},
|
|
3115
|
+
};
|
|
3116
|
+
return { success: true, data: response };
|
|
3117
|
+
}
|
|
3118
|
+
catch (error) {
|
|
3119
|
+
if (error instanceof error_types_1.NotFoundError) {
|
|
3120
|
+
return {
|
|
3121
|
+
success: false,
|
|
3122
|
+
error: {
|
|
3123
|
+
code: 'COMMENT_NOT_FOUND',
|
|
3124
|
+
message: `Comment ${validated.commentId} was not found`,
|
|
3125
|
+
},
|
|
3126
|
+
};
|
|
3127
|
+
}
|
|
3128
|
+
throw error;
|
|
3129
|
+
}
|
|
3130
|
+
}
|
|
3131
|
+
async applySuggestion(params) {
|
|
3132
|
+
const validated = mcp_dto_1.ApplySuggestionParamsSchema.parse(params);
|
|
3133
|
+
const ctx = await this.resolveSessionContext(validated.sessionId);
|
|
3134
|
+
if (!ctx.success)
|
|
3135
|
+
return ctx;
|
|
3136
|
+
const { project } = ctx.data;
|
|
3137
|
+
if (!project) {
|
|
3138
|
+
return {
|
|
3139
|
+
success: false,
|
|
3140
|
+
error: {
|
|
3141
|
+
code: 'PROJECT_NOT_FOUND',
|
|
3142
|
+
message: 'No project associated with this session',
|
|
3143
|
+
},
|
|
3144
|
+
};
|
|
3145
|
+
}
|
|
3146
|
+
if (!this.reviewsService) {
|
|
3147
|
+
return {
|
|
3148
|
+
success: false,
|
|
3149
|
+
error: {
|
|
3150
|
+
code: 'SERVICE_UNAVAILABLE',
|
|
3151
|
+
message: 'ReviewsService is not available',
|
|
3152
|
+
},
|
|
3153
|
+
};
|
|
3154
|
+
}
|
|
3155
|
+
try {
|
|
3156
|
+
const comment = await this.storage.getReviewComment(validated.commentId);
|
|
3157
|
+
const review = await this.storage.getReview(comment.reviewId);
|
|
3158
|
+
if (review.projectId !== project.id) {
|
|
3159
|
+
return {
|
|
3160
|
+
success: false,
|
|
3161
|
+
error: {
|
|
3162
|
+
code: 'COMMENT_NOT_FOUND',
|
|
3163
|
+
message: `Comment ${validated.commentId} does not belong to this project`,
|
|
3164
|
+
},
|
|
3165
|
+
};
|
|
3166
|
+
}
|
|
3167
|
+
if (!comment.filePath || comment.lineStart === null) {
|
|
3168
|
+
return {
|
|
3169
|
+
success: false,
|
|
3170
|
+
error: {
|
|
3171
|
+
code: 'INVALID_SUGGESTION',
|
|
3172
|
+
message: 'Comment does not have file path or line information',
|
|
3173
|
+
},
|
|
3174
|
+
};
|
|
3175
|
+
}
|
|
3176
|
+
const suggestionMatch = comment.content.match(/```suggestion\s*\n([\s\S]*?)```/);
|
|
3177
|
+
if (!suggestionMatch) {
|
|
3178
|
+
return {
|
|
3179
|
+
success: false,
|
|
3180
|
+
error: {
|
|
3181
|
+
code: 'NO_SUGGESTION',
|
|
3182
|
+
message: 'Comment does not contain a suggestion block',
|
|
3183
|
+
},
|
|
3184
|
+
};
|
|
3185
|
+
}
|
|
3186
|
+
const suggestedCode = suggestionMatch[1].trimEnd();
|
|
3187
|
+
const lineStart = comment.lineStart;
|
|
3188
|
+
const lineEnd = comment.lineEnd ?? comment.lineStart;
|
|
3189
|
+
let validatedPath;
|
|
3190
|
+
try {
|
|
3191
|
+
validatedPath = (0, path_validation_1.validatePathWithinRoot)(project.rootPath, comment.filePath, {
|
|
3192
|
+
errorPrefix: 'Invalid file path in comment',
|
|
3193
|
+
});
|
|
3194
|
+
}
|
|
3195
|
+
catch (error) {
|
|
3196
|
+
if (error instanceof error_types_1.ValidationError) {
|
|
3197
|
+
return {
|
|
3198
|
+
success: false,
|
|
3199
|
+
error: {
|
|
3200
|
+
code: 'PATH_TRAVERSAL_BLOCKED',
|
|
3201
|
+
message: error.message,
|
|
3202
|
+
data: error.details,
|
|
3203
|
+
},
|
|
3204
|
+
};
|
|
3205
|
+
}
|
|
3206
|
+
throw error;
|
|
3207
|
+
}
|
|
3208
|
+
let realFilePath;
|
|
3209
|
+
try {
|
|
3210
|
+
realFilePath = await (0, path_validation_1.validateResolvedPathWithinRoot)(validatedPath.absolutePath, project.rootPath, { errorPrefix: 'Symlink validation failed' });
|
|
3211
|
+
}
|
|
3212
|
+
catch (error) {
|
|
3213
|
+
if (error instanceof error_types_1.ValidationError) {
|
|
3214
|
+
return {
|
|
3215
|
+
success: false,
|
|
3216
|
+
error: {
|
|
3217
|
+
code: 'SYMLINK_ESCAPE_BLOCKED',
|
|
3218
|
+
message: error.message,
|
|
3219
|
+
data: error.details,
|
|
3220
|
+
},
|
|
3221
|
+
};
|
|
3222
|
+
}
|
|
3223
|
+
throw error;
|
|
3224
|
+
}
|
|
3225
|
+
const fs = await Promise.resolve().then(() => __importStar(require('fs/promises')));
|
|
3226
|
+
const filePath = realFilePath;
|
|
3227
|
+
const fileContent = await fs.readFile(filePath, 'utf-8');
|
|
3228
|
+
const lines = fileContent.split('\n');
|
|
3229
|
+
try {
|
|
3230
|
+
(0, path_validation_1.validateLineBounds)(lineStart, lineEnd, lines.length);
|
|
3231
|
+
}
|
|
3232
|
+
catch (error) {
|
|
3233
|
+
if (error instanceof error_types_1.ValidationError) {
|
|
3234
|
+
return {
|
|
3235
|
+
success: false,
|
|
3236
|
+
error: {
|
|
3237
|
+
code: 'INVALID_LINE_BOUNDS',
|
|
3238
|
+
message: error.message,
|
|
3239
|
+
data: error.details,
|
|
3240
|
+
},
|
|
3241
|
+
};
|
|
3242
|
+
}
|
|
3243
|
+
throw error;
|
|
3244
|
+
}
|
|
3245
|
+
const suggestedLines = suggestedCode.split('\n');
|
|
3246
|
+
lines.splice(lineStart - 1, lineEnd - lineStart + 1, ...suggestedLines);
|
|
3247
|
+
await fs.writeFile(filePath, lines.join('\n'), 'utf-8');
|
|
3248
|
+
const updatedComment = await this.reviewsService.resolveComment(comment.reviewId, validated.commentId, 'resolved', validated.version);
|
|
3249
|
+
let authorAgentName;
|
|
3250
|
+
if (updatedComment.authorAgentId) {
|
|
3251
|
+
try {
|
|
3252
|
+
const agent = await this.storage.getAgent(updatedComment.authorAgentId);
|
|
3253
|
+
authorAgentName = agent.name;
|
|
3254
|
+
}
|
|
3255
|
+
catch {
|
|
3256
|
+
}
|
|
3257
|
+
}
|
|
3258
|
+
const response = {
|
|
3259
|
+
comment: {
|
|
3260
|
+
id: updatedComment.id,
|
|
3261
|
+
filePath: updatedComment.filePath,
|
|
3262
|
+
lineStart: updatedComment.lineStart,
|
|
3263
|
+
lineEnd: updatedComment.lineEnd,
|
|
3264
|
+
side: updatedComment.side,
|
|
3265
|
+
content: updatedComment.content,
|
|
3266
|
+
commentType: updatedComment.commentType,
|
|
3267
|
+
status: updatedComment.status,
|
|
3268
|
+
authorType: updatedComment.authorType,
|
|
3269
|
+
authorAgentId: updatedComment.authorAgentId,
|
|
3270
|
+
authorAgentName,
|
|
3271
|
+
parentId: updatedComment.parentId,
|
|
3272
|
+
version: updatedComment.version,
|
|
3273
|
+
createdAt: updatedComment.createdAt,
|
|
3274
|
+
updatedAt: updatedComment.updatedAt,
|
|
3275
|
+
},
|
|
3276
|
+
applied: {
|
|
3277
|
+
filePath: comment.filePath,
|
|
3278
|
+
lineStart,
|
|
3279
|
+
lineEnd,
|
|
3280
|
+
suggestedCode,
|
|
3281
|
+
},
|
|
3282
|
+
};
|
|
3283
|
+
return { success: true, data: response };
|
|
3284
|
+
}
|
|
3285
|
+
catch (error) {
|
|
3286
|
+
if (error instanceof error_types_1.NotFoundError) {
|
|
3287
|
+
return {
|
|
3288
|
+
success: false,
|
|
3289
|
+
error: {
|
|
3290
|
+
code: 'COMMENT_NOT_FOUND',
|
|
3291
|
+
message: `Comment ${validated.commentId} was not found`,
|
|
3292
|
+
},
|
|
3293
|
+
};
|
|
3294
|
+
}
|
|
3295
|
+
if (error.code === 'ENOENT') {
|
|
3296
|
+
return {
|
|
3297
|
+
success: false,
|
|
3298
|
+
error: {
|
|
3299
|
+
code: 'FILE_NOT_FOUND',
|
|
3300
|
+
message: `File not found at path`,
|
|
3301
|
+
},
|
|
3302
|
+
};
|
|
3303
|
+
}
|
|
3304
|
+
throw error;
|
|
3305
|
+
}
|
|
3306
|
+
}
|
|
2640
3307
|
};
|
|
2641
3308
|
exports.McpService = McpService;
|
|
2642
3309
|
exports.McpService = McpService = __decorate([
|
|
@@ -2650,6 +3317,7 @@ exports.McpService = McpService = __decorate([
|
|
|
2650
3317
|
__param(6, (0, common_1.Inject)((0, common_1.forwardRef)(() => epics_service_1.EpicsService))),
|
|
2651
3318
|
__param(7, (0, common_1.Inject)((0, common_1.forwardRef)(() => settings_service_1.SettingsService))),
|
|
2652
3319
|
__param(8, (0, common_1.Inject)((0, common_1.forwardRef)(() => guests_service_1.GuestsService))),
|
|
3320
|
+
__param(9, (0, common_1.Inject)((0, common_1.forwardRef)(() => reviews_service_1.ReviewsService))),
|
|
2653
3321
|
__metadata("design:paramtypes", [Object, chat_service_1.ChatService,
|
|
2654
3322
|
sessions_service_1.SessionsService,
|
|
2655
3323
|
sessions_message_pool_service_1.SessionsMessagePoolService,
|
|
@@ -2657,6 +3325,7 @@ exports.McpService = McpService = __decorate([
|
|
|
2657
3325
|
tmux_service_1.TmuxService,
|
|
2658
3326
|
epics_service_1.EpicsService,
|
|
2659
3327
|
settings_service_1.SettingsService,
|
|
2660
|
-
guests_service_1.GuestsService
|
|
3328
|
+
guests_service_1.GuestsService,
|
|
3329
|
+
reviews_service_1.ReviewsService])
|
|
2661
3330
|
], McpService);
|
|
2662
3331
|
//# sourceMappingURL=mcp.service.js.map
|