@debugg-ai/debugg-ai-mcp 1.0.62 → 1.0.64
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/config/index.js +4 -1
- package/dist/handlers/createEnvironmentHandler.js +33 -0
- package/dist/handlers/createProjectHandler.js +62 -10
- package/dist/handlers/index.js +5 -14
- package/dist/handlers/searchEnvironmentsHandler.js +122 -0
- package/dist/handlers/searchExecutionsHandler.js +71 -0
- package/dist/handlers/searchProjectsHandler.js +72 -0
- package/dist/handlers/testPageChangesHandler.js +46 -5
- package/dist/handlers/triggerCrawlHandler.js +208 -0
- package/dist/handlers/updateEnvironmentHandler.js +94 -15
- package/dist/index.js +15 -2
- package/dist/services/workflows.js +10 -6
- package/dist/tools/createEnvironment.js +5 -1
- package/dist/tools/index.js +12 -42
- package/dist/tools/searchEnvironments.js +35 -0
- package/dist/tools/searchExecutions.js +31 -0
- package/dist/tools/searchProjects.js +30 -0
- package/dist/tools/triggerCrawl.js +99 -0
- package/dist/types/index.js +64 -71
- package/package.json +4 -1
- package/dist/handlers/cancelExecutionHandler.js +0 -41
- package/dist/handlers/createCredentialHandler.js +0 -60
- package/dist/handlers/deleteCredentialHandler.js +0 -51
- package/dist/handlers/getCredentialHandler.js +0 -49
- package/dist/handlers/getEnvironmentHandler.js +0 -49
- package/dist/handlers/getExecutionHandler.js +0 -37
- package/dist/handlers/getProjectHandler.js +0 -37
- package/dist/handlers/listCredentialsHandler.js +0 -93
- package/dist/handlers/listEnvironmentsHandler.js +0 -63
- package/dist/handlers/listExecutionsHandler.js +0 -35
- package/dist/handlers/listProjectsHandler.js +0 -32
- package/dist/handlers/listReposHandler.js +0 -27
- package/dist/handlers/listTeamsHandler.js +0 -27
- package/dist/handlers/updateCredentialHandler.js +0 -70
- package/dist/tools/cancelExecution.js +0 -22
- package/dist/tools/createCredential.js +0 -52
- package/dist/tools/deleteCredential.js +0 -24
- package/dist/tools/getCredential.js +0 -24
- package/dist/tools/getEnvironment.js +0 -23
- package/dist/tools/getExecution.js +0 -22
- package/dist/tools/getProject.js +0 -22
- package/dist/tools/listCredentials.js +0 -30
- package/dist/tools/listEnvironments.js +0 -28
- package/dist/tools/listExecutions.js +0 -24
- package/dist/tools/listProjects.js +0 -27
- package/dist/tools/listRepos.js +0 -23
- package/dist/tools/listTeams.js +0 -23
- package/dist/tools/updateCredential.js +0 -28
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trigger Crawl Tool Definition
|
|
3
|
+
* Defines the trigger_crawl tool with proper validation.
|
|
4
|
+
* Tool description is enriched at startup with available environments/credentials.
|
|
5
|
+
*/
|
|
6
|
+
import { TriggerCrawlInputSchema } from '../types/index.js';
|
|
7
|
+
import { triggerCrawlHandler } from '../handlers/triggerCrawlHandler.js';
|
|
8
|
+
const BASE_DESCRIPTION = `Trigger a browser-agent crawl of a web app to build the project's knowledge graph. The crawl systematically explores pages, UI states, and navigation flows, then populates the backend's knowledge graph so future evaluations and tests have context about the app.
|
|
9
|
+
|
|
10
|
+
LOCALHOST SUPPORT: Pass any localhost URL (e.g. http://localhost:3000) and it Just Works. A secure tunnel is automatically created so the remote browser can reach your local dev server.
|
|
11
|
+
|
|
12
|
+
WHEN TO USE: after a significant new feature, a new environment, or when onboarding a project. NOT for per-change verification — use check_app_in_browser for that.
|
|
13
|
+
|
|
14
|
+
SCOPE: one crawl per call against one URL. The crawl is long-running (minutes to tens of minutes depending on app size) and populates backend state asynchronously; the tool returns the execution status once the workflow completes. This does NOT return pass/fail — it returns executionId + status + outcome.`;
|
|
15
|
+
export function buildTriggerCrawlDescription(ctx) {
|
|
16
|
+
if (!ctx)
|
|
17
|
+
return BASE_DESCRIPTION;
|
|
18
|
+
const envsWithCreds = ctx.environments.filter(e => e.credentials.length > 0);
|
|
19
|
+
if (envsWithCreds.length === 0) {
|
|
20
|
+
return `${BASE_DESCRIPTION}\n\nDETECTED PROJECT: "${ctx.project.name}" (repo: ${ctx.repoName}). No credentials configured — provide username/password if the app requires login to crawl authenticated areas.`;
|
|
21
|
+
}
|
|
22
|
+
const lines = [
|
|
23
|
+
`\n\nDETECTED PROJECT: "${ctx.project.name}" (repo: ${ctx.repoName})`,
|
|
24
|
+
`\nAVAILABLE ENVIRONMENTS & CREDENTIALS (pass environmentId + credentialId to crawl authenticated areas):`,
|
|
25
|
+
];
|
|
26
|
+
for (const env of envsWithCreds) {
|
|
27
|
+
lines.push(`\n Environment: "${env.name}" (${env.uuid})${env.url ? ` — ${env.url}` : ''}`);
|
|
28
|
+
for (const cred of env.credentials) {
|
|
29
|
+
const parts = [` - "${cred.label}" (${cred.uuid}) — user: ${cred.username}`];
|
|
30
|
+
if (cred.role)
|
|
31
|
+
parts[0] += `, role: ${cred.role}`;
|
|
32
|
+
lines.push(parts[0]);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
lines.push(`\nTo use: pass environmentId and credentialId from above. Or provide username/password directly.`);
|
|
36
|
+
return BASE_DESCRIPTION + lines.join('\n');
|
|
37
|
+
}
|
|
38
|
+
export function buildTriggerCrawlTool(ctx) {
|
|
39
|
+
return {
|
|
40
|
+
name: 'trigger_crawl',
|
|
41
|
+
title: 'Trigger App Crawl',
|
|
42
|
+
description: buildTriggerCrawlDescription(ctx),
|
|
43
|
+
inputSchema: {
|
|
44
|
+
type: 'object',
|
|
45
|
+
properties: {
|
|
46
|
+
url: {
|
|
47
|
+
type: 'string',
|
|
48
|
+
description: 'URL to crawl. Can be any public URL or a localhost/local dev server URL. For localhost URLs, a secure tunnel is automatically created — just make sure your dev server is running on that port.',
|
|
49
|
+
},
|
|
50
|
+
projectUuid: {
|
|
51
|
+
type: 'string',
|
|
52
|
+
description: 'UUID of the project whose knowledge graph the crawl should populate. Auto-detected from the current git repo if omitted.',
|
|
53
|
+
},
|
|
54
|
+
environmentId: {
|
|
55
|
+
type: 'string',
|
|
56
|
+
description: 'UUID of a specific environment to use for the crawl. See available environments in the tool description above.',
|
|
57
|
+
},
|
|
58
|
+
credentialId: {
|
|
59
|
+
type: 'string',
|
|
60
|
+
description: 'UUID of a specific credential for authenticated crawls. See available credentials in the tool description above.',
|
|
61
|
+
},
|
|
62
|
+
credentialRole: {
|
|
63
|
+
type: 'string',
|
|
64
|
+
description: "Pick a credential by role (e.g. 'admin', 'guest') from the resolved environment.",
|
|
65
|
+
},
|
|
66
|
+
username: {
|
|
67
|
+
type: 'string',
|
|
68
|
+
description: 'A real, existing account email for the target app. Do NOT invent credentials — use one from the available credentials or ask the user.',
|
|
69
|
+
},
|
|
70
|
+
password: {
|
|
71
|
+
type: 'string',
|
|
72
|
+
description: 'The real password for the username above. Do NOT guess.',
|
|
73
|
+
},
|
|
74
|
+
headless: {
|
|
75
|
+
type: 'boolean',
|
|
76
|
+
description: 'Run the browser in headless mode. Defaults to backend configuration.',
|
|
77
|
+
},
|
|
78
|
+
timeoutSeconds: {
|
|
79
|
+
type: 'number',
|
|
80
|
+
description: 'Maximum wall-time the crawl may run, in seconds (1..1800). Backend enforces this per workflow execution.',
|
|
81
|
+
},
|
|
82
|
+
repoName: {
|
|
83
|
+
type: 'string',
|
|
84
|
+
description: "GitHub repository name (e.g. 'my-org/my-repo'). Auto-detected from the current git repo — only provide this to run against a different project.",
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
required: ['url'],
|
|
88
|
+
additionalProperties: false,
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
export function buildValidatedTriggerCrawlTool(ctx) {
|
|
93
|
+
const tool = buildTriggerCrawlTool(ctx);
|
|
94
|
+
return {
|
|
95
|
+
...tool,
|
|
96
|
+
inputSchema: TriggerCrawlInputSchema,
|
|
97
|
+
handler: triggerCrawlHandler,
|
|
98
|
+
};
|
|
99
|
+
}
|
package/dist/types/index.js
CHANGED
|
@@ -17,21 +17,62 @@ export const TestPageChangesInputSchema = z.object({
|
|
|
17
17
|
password: z.string().optional(),
|
|
18
18
|
repoName: z.string().optional(),
|
|
19
19
|
});
|
|
20
|
-
export const
|
|
20
|
+
export const TriggerCrawlInputSchema = z.object({
|
|
21
|
+
url: z.preprocess(normalizeUrl, z.string().url('Invalid URL. Pass a full URL like "http://localhost:3000" or "https://example.com". Localhost URLs are auto-tunneled to the remote browser.')),
|
|
21
22
|
projectUuid: z.string().uuid().optional(),
|
|
23
|
+
environmentId: z.string().uuid().optional(),
|
|
24
|
+
credentialId: z.string().uuid().optional(),
|
|
25
|
+
credentialRole: z.string().optional(),
|
|
26
|
+
username: z.string().optional(),
|
|
27
|
+
password: z.string().optional(),
|
|
28
|
+
headless: z.boolean().optional(),
|
|
29
|
+
timeoutSeconds: z.number().int().positive().max(1800, 'timeoutSeconds cannot exceed 1800 (30 min)').optional(),
|
|
30
|
+
repoName: z.string().optional(),
|
|
31
|
+
}).strict();
|
|
32
|
+
// ── New consolidated search schemas (bead ddq) ─────────────────────────────
|
|
33
|
+
// uuid and filter params are mutually exclusive: either look up one thing by
|
|
34
|
+
// uuid, or filter the collection. Mixing them is ambiguous.
|
|
35
|
+
export const SearchProjectsInputSchema = z.object({
|
|
36
|
+
uuid: z.string().uuid().optional(),
|
|
22
37
|
q: z.string().min(1).optional(),
|
|
23
38
|
page: z.number().int().min(1).optional(),
|
|
24
39
|
pageSize: z.number().int().min(1).optional(),
|
|
40
|
+
}).strict().refine((v) => !(v.uuid && (v.q !== undefined)), { message: 'Cannot combine uuid with filter params (q). Pass one or the other.' });
|
|
41
|
+
// projectUuid is a LOCATOR (required by the backend URL path for envs/creds), not a
|
|
42
|
+
// filter — so it's compatible with uuid mode. Only q and uuid are mutually exclusive.
|
|
43
|
+
export const SearchEnvironmentsInputSchema = z.object({
|
|
44
|
+
uuid: z.string().uuid().optional(),
|
|
45
|
+
projectUuid: z.string().uuid().optional(),
|
|
46
|
+
q: z.string().min(1).optional(),
|
|
47
|
+
page: z.number().int().min(1).optional(),
|
|
48
|
+
pageSize: z.number().int().min(1).optional(),
|
|
49
|
+
}).strict().refine((v) => !(v.uuid && v.q !== undefined), { message: 'Cannot combine uuid with q (they are mutually exclusive — uuid mode returns one env; q filters a list).' });
|
|
50
|
+
export const SearchExecutionsInputSchema = z.object({
|
|
51
|
+
uuid: z.string().uuid().optional(),
|
|
52
|
+
projectUuid: z.string().uuid().optional(),
|
|
53
|
+
status: z.string().min(1).optional(),
|
|
54
|
+
page: z.number().int().min(1).optional(),
|
|
55
|
+
pageSize: z.number().int().min(1).optional(),
|
|
56
|
+
}).strict().refine((v) => !(v.uuid && (v.projectUuid || v.status)), { message: 'Cannot combine uuid with filter params (projectUuid, status).' });
|
|
57
|
+
const CredentialSeedSchema = z.object({
|
|
58
|
+
label: z.string().min(1, 'label is required'),
|
|
59
|
+
username: z.string().min(1, 'username is required'),
|
|
60
|
+
password: z.string().min(1, 'password is required'),
|
|
61
|
+
role: z.string().min(1).optional(),
|
|
25
62
|
}).strict();
|
|
26
63
|
export const CreateEnvironmentInputSchema = z.object({
|
|
27
64
|
name: z.string().min(1, 'name is required'),
|
|
28
65
|
url: z.string().url('url is required for standard environments'),
|
|
29
66
|
description: z.string().optional(),
|
|
30
67
|
projectUuid: z.string().uuid().optional(),
|
|
68
|
+
credentials: z.array(CredentialSeedSchema).optional(),
|
|
31
69
|
}).strict();
|
|
32
|
-
|
|
70
|
+
const CredentialUpdateSchema = z.object({
|
|
33
71
|
uuid: z.string().uuid(),
|
|
34
|
-
|
|
72
|
+
label: z.string().min(1).optional(),
|
|
73
|
+
username: z.string().min(1).optional(),
|
|
74
|
+
password: z.string().min(1).optional(),
|
|
75
|
+
role: z.string().min(1).optional(),
|
|
35
76
|
}).strict();
|
|
36
77
|
export const UpdateEnvironmentInputSchema = z.object({
|
|
37
78
|
uuid: z.string().uuid(),
|
|
@@ -39,33 +80,14 @@ export const UpdateEnvironmentInputSchema = z.object({
|
|
|
39
80
|
url: z.string().url().optional(),
|
|
40
81
|
description: z.string().optional(),
|
|
41
82
|
projectUuid: z.string().uuid().optional(),
|
|
83
|
+
addCredentials: z.array(CredentialSeedSchema).optional(),
|
|
84
|
+
updateCredentials: z.array(CredentialUpdateSchema).optional(),
|
|
85
|
+
removeCredentialIds: z.array(z.string().uuid()).optional(),
|
|
42
86
|
}).strict();
|
|
43
87
|
export const DeleteEnvironmentInputSchema = z.object({
|
|
44
88
|
uuid: z.string().uuid(),
|
|
45
89
|
projectUuid: z.string().uuid().optional(),
|
|
46
90
|
}).strict();
|
|
47
|
-
export const GetCredentialInputSchema = z.object({
|
|
48
|
-
uuid: z.string().uuid(),
|
|
49
|
-
environmentId: z.string().uuid(),
|
|
50
|
-
projectUuid: z.string().uuid().optional(),
|
|
51
|
-
}).strict();
|
|
52
|
-
export const UpdateCredentialInputSchema = z.object({
|
|
53
|
-
uuid: z.string().uuid(),
|
|
54
|
-
environmentId: z.string().uuid(),
|
|
55
|
-
label: z.string().min(1).optional(),
|
|
56
|
-
username: z.string().min(1).optional(),
|
|
57
|
-
password: z.string().min(1).optional(),
|
|
58
|
-
role: z.string().min(1).optional(),
|
|
59
|
-
projectUuid: z.string().uuid().optional(),
|
|
60
|
-
}).strict();
|
|
61
|
-
export const DeleteCredentialInputSchema = z.object({
|
|
62
|
-
uuid: z.string().uuid(),
|
|
63
|
-
environmentId: z.string().uuid(),
|
|
64
|
-
projectUuid: z.string().uuid().optional(),
|
|
65
|
-
}).strict();
|
|
66
|
-
export const GetProjectInputSchema = z.object({
|
|
67
|
-
uuid: z.string().uuid(),
|
|
68
|
-
}).strict();
|
|
69
91
|
export const UpdateProjectInputSchema = z.object({
|
|
70
92
|
uuid: z.string().uuid(),
|
|
71
93
|
name: z.string().min(1).optional(),
|
|
@@ -74,55 +96,26 @@ export const UpdateProjectInputSchema = z.object({
|
|
|
74
96
|
export const DeleteProjectInputSchema = z.object({
|
|
75
97
|
uuid: z.string().uuid(),
|
|
76
98
|
}).strict();
|
|
77
|
-
export const ListExecutionsInputSchema = z.object({
|
|
78
|
-
status: z.string().min(1).optional(),
|
|
79
|
-
projectUuid: z.string().uuid().optional(),
|
|
80
|
-
page: z.number().int().min(1).optional(),
|
|
81
|
-
pageSize: z.number().int().min(1).optional(),
|
|
82
|
-
}).strict();
|
|
83
|
-
export const GetExecutionInputSchema = z.object({
|
|
84
|
-
uuid: z.string().uuid(),
|
|
85
|
-
}).strict();
|
|
86
|
-
export const CancelExecutionInputSchema = z.object({
|
|
87
|
-
uuid: z.string().uuid(),
|
|
88
|
-
}).strict();
|
|
89
|
-
export const ListCredentialsInputSchema = z.object({
|
|
90
|
-
environmentId: z.string().uuid().optional(),
|
|
91
|
-
projectUuid: z.string().uuid().optional(),
|
|
92
|
-
q: z.string().min(1).optional(),
|
|
93
|
-
role: z.string().min(1).optional(),
|
|
94
|
-
page: z.number().int().min(1).optional(),
|
|
95
|
-
pageSize: z.number().int().min(1).optional(),
|
|
96
|
-
}).strict();
|
|
97
|
-
export const CreateCredentialInputSchema = z.object({
|
|
98
|
-
environmentId: z.string().uuid(),
|
|
99
|
-
label: z.string().min(1, 'label is required'),
|
|
100
|
-
username: z.string().min(1, 'username is required'),
|
|
101
|
-
password: z.string().min(1, 'password is required'),
|
|
102
|
-
role: z.string().min(1).optional(),
|
|
103
|
-
projectUuid: z.string().uuid().optional(),
|
|
104
|
-
}).strict();
|
|
105
|
-
export const ListProjectsInputSchema = z.object({
|
|
106
|
-
q: z.string().min(1).optional(),
|
|
107
|
-
page: z.number().int().min(1).optional(),
|
|
108
|
-
pageSize: z.number().int().min(1).optional(),
|
|
109
|
-
}).strict();
|
|
110
|
-
export const ListTeamsInputSchema = z.object({
|
|
111
|
-
q: z.string().min(1).optional(),
|
|
112
|
-
page: z.number().int().min(1).optional(),
|
|
113
|
-
pageSize: z.number().int().min(1).optional(),
|
|
114
|
-
}).strict();
|
|
115
|
-
export const ListReposInputSchema = z.object({
|
|
116
|
-
q: z.string().min(1).optional(),
|
|
117
|
-
page: z.number().int().min(1).optional(),
|
|
118
|
-
pageSize: z.number().int().min(1).optional(),
|
|
119
|
-
}).strict();
|
|
120
99
|
export const CreateProjectInputSchema = z.object({
|
|
121
100
|
name: z.string().min(1),
|
|
122
101
|
platform: z.string().min(1),
|
|
123
|
-
teamUuid: z.string().uuid(),
|
|
124
|
-
|
|
125
|
-
|
|
102
|
+
teamUuid: z.string().uuid().optional(),
|
|
103
|
+
teamName: z.string().min(1).optional(),
|
|
104
|
+
repoUuid: z.string().uuid().optional(),
|
|
105
|
+
repoName: z.string().min(1).optional(),
|
|
106
|
+
}).strict()
|
|
107
|
+
.refine((v) => !(v.teamUuid && v.teamName), {
|
|
108
|
+
message: 'Provide teamUuid OR teamName, not both.',
|
|
109
|
+
})
|
|
110
|
+
.refine((v) => !(v.repoUuid && v.repoName), {
|
|
111
|
+
message: 'Provide repoUuid OR repoName, not both.',
|
|
112
|
+
})
|
|
113
|
+
.refine((v) => v.teamUuid || v.teamName, {
|
|
114
|
+
message: 'Must provide teamUuid or teamName.',
|
|
115
|
+
})
|
|
116
|
+
.refine((v) => v.repoUuid || v.repoName, {
|
|
117
|
+
message: 'Must provide repoUuid or repoName.',
|
|
118
|
+
});
|
|
126
119
|
/**
|
|
127
120
|
* Error types
|
|
128
121
|
*/
|
package/package.json
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@debugg-ai/debugg-ai-mcp",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.64",
|
|
4
4
|
"description": "Zero-Config, Fully AI-Managed End-to-End Testing for all code gen platforms.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"debugg-ai-mcp": "dist/index.js"
|
|
8
8
|
},
|
|
9
|
+
"engines": {
|
|
10
|
+
"node": ">=20.20.0"
|
|
11
|
+
},
|
|
9
12
|
"files": [
|
|
10
13
|
"dist"
|
|
11
14
|
],
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { Logger } from '../utils/logger.js';
|
|
2
|
-
import { handleExternalServiceError } from '../utils/errors.js';
|
|
3
|
-
import { DebuggAIServerClient } from '../services/index.js';
|
|
4
|
-
import { config } from '../config/index.js';
|
|
5
|
-
const logger = new Logger({ module: 'cancelExecutionHandler' });
|
|
6
|
-
function errorResponse(error, message, uuid) {
|
|
7
|
-
return {
|
|
8
|
-
content: [{ type: 'text', text: JSON.stringify({ error, message, uuid }, null, 2) }],
|
|
9
|
-
isError: true,
|
|
10
|
-
};
|
|
11
|
-
}
|
|
12
|
-
export async function cancelExecutionHandler(input, _context) {
|
|
13
|
-
const start = Date.now();
|
|
14
|
-
logger.toolStart('cancel_execution', { uuid: input.uuid });
|
|
15
|
-
try {
|
|
16
|
-
const client = new DebuggAIServerClient(config.api.key);
|
|
17
|
-
await client.init();
|
|
18
|
-
try {
|
|
19
|
-
await client.workflows.cancelExecution(input.uuid);
|
|
20
|
-
logger.toolComplete('cancel_execution', Date.now() - start);
|
|
21
|
-
return {
|
|
22
|
-
content: [{ type: 'text', text: JSON.stringify({ cancelled: true, uuid: input.uuid }, null, 2) }],
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
catch (err) {
|
|
26
|
-
const status = err?.statusCode ?? err?.response?.status;
|
|
27
|
-
const detail = err?.responseData?.error ?? err?.message ?? '';
|
|
28
|
-
if (status === 404) {
|
|
29
|
-
return errorResponse('NotFound', `Execution ${input.uuid} not found.`, input.uuid);
|
|
30
|
-
}
|
|
31
|
-
if (status === 409 || /already|completed|cannot.?cancel/i.test(detail)) {
|
|
32
|
-
return errorResponse('AlreadyCompleted', detail || `Execution ${input.uuid} cannot be cancelled.`, input.uuid);
|
|
33
|
-
}
|
|
34
|
-
throw err;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
catch (error) {
|
|
38
|
-
logger.toolError('cancel_execution', error, Date.now() - start);
|
|
39
|
-
throw handleExternalServiceError(error, 'DebuggAI', 'cancel_execution');
|
|
40
|
-
}
|
|
41
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { Logger } from '../utils/logger.js';
|
|
2
|
-
import { handleExternalServiceError } from '../utils/errors.js';
|
|
3
|
-
import { DebuggAIServerClient } from '../services/index.js';
|
|
4
|
-
import { config } from '../config/index.js';
|
|
5
|
-
import { detectRepoName } from '../utils/gitContext.js';
|
|
6
|
-
const logger = new Logger({ module: 'createCredentialHandler' });
|
|
7
|
-
export async function createCredentialHandler(input, _context) {
|
|
8
|
-
const start = Date.now();
|
|
9
|
-
logger.toolStart('create_credential', {
|
|
10
|
-
environmentId: input.environmentId,
|
|
11
|
-
label: input.label,
|
|
12
|
-
hasRole: !!input.role,
|
|
13
|
-
projectUuid: input.projectUuid,
|
|
14
|
-
});
|
|
15
|
-
try {
|
|
16
|
-
const client = new DebuggAIServerClient(config.api.key);
|
|
17
|
-
await client.init();
|
|
18
|
-
let projectUuid = input.projectUuid;
|
|
19
|
-
if (!projectUuid) {
|
|
20
|
-
const repoName = detectRepoName();
|
|
21
|
-
if (!repoName) {
|
|
22
|
-
return {
|
|
23
|
-
content: [{ type: 'text', text: JSON.stringify({
|
|
24
|
-
error: 'NoProjectResolved',
|
|
25
|
-
message: 'No git repo detected and no projectUuid provided. Pass projectUuid (get it from list_projects) or invoke from a directory with a git origin.',
|
|
26
|
-
}, null, 2) }],
|
|
27
|
-
isError: true,
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
const project = await client.findProjectByRepoName(repoName);
|
|
31
|
-
if (!project) {
|
|
32
|
-
return {
|
|
33
|
-
content: [{ type: 'text', text: JSON.stringify({
|
|
34
|
-
error: 'NoProjectResolved',
|
|
35
|
-
message: `No DebuggAI project found for repo "${repoName}". Pass projectUuid explicitly.`,
|
|
36
|
-
}, null, 2) }],
|
|
37
|
-
isError: true,
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
projectUuid = project.uuid;
|
|
41
|
-
}
|
|
42
|
-
const cred = await client.createCredential(projectUuid, input.environmentId, {
|
|
43
|
-
label: input.label,
|
|
44
|
-
username: input.username,
|
|
45
|
-
password: input.password,
|
|
46
|
-
role: input.role,
|
|
47
|
-
});
|
|
48
|
-
const payload = {
|
|
49
|
-
created: true,
|
|
50
|
-
projectUuid,
|
|
51
|
-
credential: cred,
|
|
52
|
-
};
|
|
53
|
-
logger.toolComplete('create_credential', Date.now() - start);
|
|
54
|
-
return { content: [{ type: 'text', text: JSON.stringify(payload, null, 2) }] };
|
|
55
|
-
}
|
|
56
|
-
catch (error) {
|
|
57
|
-
logger.toolError('create_credential', error, Date.now() - start);
|
|
58
|
-
throw handleExternalServiceError(error, 'DebuggAI', 'create_credential');
|
|
59
|
-
}
|
|
60
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { Logger } from '../utils/logger.js';
|
|
2
|
-
import { handleExternalServiceError } from '../utils/errors.js';
|
|
3
|
-
import { DebuggAIServerClient } from '../services/index.js';
|
|
4
|
-
import { config } from '../config/index.js';
|
|
5
|
-
import { detectRepoName } from '../utils/gitContext.js';
|
|
6
|
-
const logger = new Logger({ module: 'deleteCredentialHandler' });
|
|
7
|
-
function notFound(uuid, context) {
|
|
8
|
-
return {
|
|
9
|
-
content: [{ type: 'text', text: JSON.stringify({
|
|
10
|
-
error: 'NotFound',
|
|
11
|
-
message: `Credential ${uuid} not found (${context}).`,
|
|
12
|
-
uuid,
|
|
13
|
-
}, null, 2) }],
|
|
14
|
-
isError: true,
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
export async function deleteCredentialHandler(input, _context) {
|
|
18
|
-
const start = Date.now();
|
|
19
|
-
logger.toolStart('delete_credential', { uuid: input.uuid, environmentId: input.environmentId });
|
|
20
|
-
try {
|
|
21
|
-
const client = new DebuggAIServerClient(config.api.key);
|
|
22
|
-
await client.init();
|
|
23
|
-
let projectUuid = input.projectUuid;
|
|
24
|
-
if (!projectUuid) {
|
|
25
|
-
const repoName = detectRepoName();
|
|
26
|
-
if (!repoName)
|
|
27
|
-
return notFound(input.uuid, 'no git repo and no projectUuid');
|
|
28
|
-
const project = await client.findProjectByRepoName(repoName);
|
|
29
|
-
if (!project)
|
|
30
|
-
return notFound(input.uuid, `no project for repo "${repoName}"`);
|
|
31
|
-
projectUuid = project.uuid;
|
|
32
|
-
}
|
|
33
|
-
try {
|
|
34
|
-
await client.deleteCredential(projectUuid, input.environmentId, input.uuid);
|
|
35
|
-
logger.toolComplete('delete_credential', Date.now() - start);
|
|
36
|
-
return {
|
|
37
|
-
content: [{ type: 'text', text: JSON.stringify({ deleted: true, uuid: input.uuid }, null, 2) }],
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
catch (err) {
|
|
41
|
-
if (err?.statusCode === 404 || err?.response?.status === 404) {
|
|
42
|
-
return notFound(input.uuid, `backend 404 for env ${input.environmentId}`);
|
|
43
|
-
}
|
|
44
|
-
throw err;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
catch (error) {
|
|
48
|
-
logger.toolError('delete_credential', error, Date.now() - start);
|
|
49
|
-
throw handleExternalServiceError(error, 'DebuggAI', 'delete_credential');
|
|
50
|
-
}
|
|
51
|
-
}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { Logger } from '../utils/logger.js';
|
|
2
|
-
import { handleExternalServiceError } from '../utils/errors.js';
|
|
3
|
-
import { DebuggAIServerClient } from '../services/index.js';
|
|
4
|
-
import { config } from '../config/index.js';
|
|
5
|
-
import { detectRepoName } from '../utils/gitContext.js';
|
|
6
|
-
const logger = new Logger({ module: 'getCredentialHandler' });
|
|
7
|
-
function notFound(uuid, context) {
|
|
8
|
-
return {
|
|
9
|
-
content: [{ type: 'text', text: JSON.stringify({
|
|
10
|
-
error: 'NotFound',
|
|
11
|
-
message: `Credential ${uuid} not found (${context}).`,
|
|
12
|
-
uuid,
|
|
13
|
-
}, null, 2) }],
|
|
14
|
-
isError: true,
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
export async function getCredentialHandler(input, _context) {
|
|
18
|
-
const start = Date.now();
|
|
19
|
-
logger.toolStart('get_credential', { uuid: input.uuid, environmentId: input.environmentId, projectUuid: input.projectUuid });
|
|
20
|
-
try {
|
|
21
|
-
const client = new DebuggAIServerClient(config.api.key);
|
|
22
|
-
await client.init();
|
|
23
|
-
let projectUuid = input.projectUuid;
|
|
24
|
-
if (!projectUuid) {
|
|
25
|
-
const repoName = detectRepoName();
|
|
26
|
-
if (!repoName)
|
|
27
|
-
return notFound(input.uuid, 'no git repo and no projectUuid');
|
|
28
|
-
const project = await client.findProjectByRepoName(repoName);
|
|
29
|
-
if (!project)
|
|
30
|
-
return notFound(input.uuid, `no project for repo "${repoName}"`);
|
|
31
|
-
projectUuid = project.uuid;
|
|
32
|
-
}
|
|
33
|
-
try {
|
|
34
|
-
const credential = await client.getCredential(projectUuid, input.environmentId, input.uuid);
|
|
35
|
-
logger.toolComplete('get_credential', Date.now() - start);
|
|
36
|
-
return { content: [{ type: 'text', text: JSON.stringify({ credential }, null, 2) }] };
|
|
37
|
-
}
|
|
38
|
-
catch (err) {
|
|
39
|
-
if (err?.statusCode === 404 || err?.response?.status === 404) {
|
|
40
|
-
return notFound(input.uuid, `backend 404 for env ${input.environmentId}`);
|
|
41
|
-
}
|
|
42
|
-
throw err;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
catch (error) {
|
|
46
|
-
logger.toolError('get_credential', error, Date.now() - start);
|
|
47
|
-
throw handleExternalServiceError(error, 'DebuggAI', 'get_credential');
|
|
48
|
-
}
|
|
49
|
-
}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { Logger } from '../utils/logger.js';
|
|
2
|
-
import { handleExternalServiceError } from '../utils/errors.js';
|
|
3
|
-
import { DebuggAIServerClient } from '../services/index.js';
|
|
4
|
-
import { config } from '../config/index.js';
|
|
5
|
-
import { detectRepoName } from '../utils/gitContext.js';
|
|
6
|
-
const logger = new Logger({ module: 'getEnvironmentHandler' });
|
|
7
|
-
function notFound(uuid, context) {
|
|
8
|
-
return {
|
|
9
|
-
content: [{ type: 'text', text: JSON.stringify({
|
|
10
|
-
error: 'NotFound',
|
|
11
|
-
message: `Environment ${uuid} not found (${context}).`,
|
|
12
|
-
uuid,
|
|
13
|
-
}, null, 2) }],
|
|
14
|
-
isError: true,
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
export async function getEnvironmentHandler(input, _context) {
|
|
18
|
-
const start = Date.now();
|
|
19
|
-
logger.toolStart('get_environment', { uuid: input.uuid, projectUuid: input.projectUuid });
|
|
20
|
-
try {
|
|
21
|
-
const client = new DebuggAIServerClient(config.api.key);
|
|
22
|
-
await client.init();
|
|
23
|
-
let projectUuid = input.projectUuid;
|
|
24
|
-
if (!projectUuid) {
|
|
25
|
-
const repoName = detectRepoName();
|
|
26
|
-
if (!repoName)
|
|
27
|
-
return notFound(input.uuid, 'no git repo detected and no projectUuid provided');
|
|
28
|
-
const project = await client.findProjectByRepoName(repoName);
|
|
29
|
-
if (!project)
|
|
30
|
-
return notFound(input.uuid, `no project found for repo "${repoName}"`);
|
|
31
|
-
projectUuid = project.uuid;
|
|
32
|
-
}
|
|
33
|
-
try {
|
|
34
|
-
const environment = await client.getEnvironment(projectUuid, input.uuid);
|
|
35
|
-
logger.toolComplete('get_environment', Date.now() - start);
|
|
36
|
-
return { content: [{ type: 'text', text: JSON.stringify({ environment }, null, 2) }] };
|
|
37
|
-
}
|
|
38
|
-
catch (err) {
|
|
39
|
-
if (err?.statusCode === 404 || err?.response?.status === 404) {
|
|
40
|
-
return notFound(input.uuid, `backend returned 404 for project ${projectUuid}`);
|
|
41
|
-
}
|
|
42
|
-
throw err;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
catch (error) {
|
|
46
|
-
logger.toolError('get_environment', error, Date.now() - start);
|
|
47
|
-
throw handleExternalServiceError(error, 'DebuggAI', 'get_environment');
|
|
48
|
-
}
|
|
49
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { Logger } from '../utils/logger.js';
|
|
2
|
-
import { handleExternalServiceError } from '../utils/errors.js';
|
|
3
|
-
import { DebuggAIServerClient } from '../services/index.js';
|
|
4
|
-
import { config } from '../config/index.js';
|
|
5
|
-
const logger = new Logger({ module: 'getExecutionHandler' });
|
|
6
|
-
function notFound(uuid) {
|
|
7
|
-
return {
|
|
8
|
-
content: [{ type: 'text', text: JSON.stringify({
|
|
9
|
-
error: 'NotFound',
|
|
10
|
-
message: `Execution ${uuid} not found.`,
|
|
11
|
-
uuid,
|
|
12
|
-
}, null, 2) }],
|
|
13
|
-
isError: true,
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
export async function getExecutionHandler(input, _context) {
|
|
17
|
-
const start = Date.now();
|
|
18
|
-
logger.toolStart('get_execution', { uuid: input.uuid });
|
|
19
|
-
try {
|
|
20
|
-
const client = new DebuggAIServerClient(config.api.key);
|
|
21
|
-
await client.init();
|
|
22
|
-
try {
|
|
23
|
-
const execution = await client.workflows.getExecution(input.uuid);
|
|
24
|
-
logger.toolComplete('get_execution', Date.now() - start);
|
|
25
|
-
return { content: [{ type: 'text', text: JSON.stringify({ execution }, null, 2) }] };
|
|
26
|
-
}
|
|
27
|
-
catch (err) {
|
|
28
|
-
if (err?.statusCode === 404 || err?.response?.status === 404)
|
|
29
|
-
return notFound(input.uuid);
|
|
30
|
-
throw err;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
catch (error) {
|
|
34
|
-
logger.toolError('get_execution', error, Date.now() - start);
|
|
35
|
-
throw handleExternalServiceError(error, 'DebuggAI', 'get_execution');
|
|
36
|
-
}
|
|
37
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { Logger } from '../utils/logger.js';
|
|
2
|
-
import { handleExternalServiceError } from '../utils/errors.js';
|
|
3
|
-
import { DebuggAIServerClient } from '../services/index.js';
|
|
4
|
-
import { config } from '../config/index.js';
|
|
5
|
-
const logger = new Logger({ module: 'getProjectHandler' });
|
|
6
|
-
function notFound(uuid) {
|
|
7
|
-
return {
|
|
8
|
-
content: [{ type: 'text', text: JSON.stringify({
|
|
9
|
-
error: 'NotFound',
|
|
10
|
-
message: `Project ${uuid} not found.`,
|
|
11
|
-
uuid,
|
|
12
|
-
}, null, 2) }],
|
|
13
|
-
isError: true,
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
export async function getProjectHandler(input, _context) {
|
|
17
|
-
const start = Date.now();
|
|
18
|
-
logger.toolStart('get_project', { uuid: input.uuid });
|
|
19
|
-
try {
|
|
20
|
-
const client = new DebuggAIServerClient(config.api.key);
|
|
21
|
-
await client.init();
|
|
22
|
-
try {
|
|
23
|
-
const project = await client.getProject(input.uuid);
|
|
24
|
-
logger.toolComplete('get_project', Date.now() - start);
|
|
25
|
-
return { content: [{ type: 'text', text: JSON.stringify({ project }, null, 2) }] };
|
|
26
|
-
}
|
|
27
|
-
catch (err) {
|
|
28
|
-
if (err?.statusCode === 404 || err?.response?.status === 404)
|
|
29
|
-
return notFound(input.uuid);
|
|
30
|
-
throw err;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
catch (error) {
|
|
34
|
-
logger.toolError('get_project', error, Date.now() - start);
|
|
35
|
-
throw handleExternalServiceError(error, 'DebuggAI', 'get_project');
|
|
36
|
-
}
|
|
37
|
-
}
|