@gitlab/gitlab-ai-provider 3.1.0 → 3.1.2

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/index.js CHANGED
@@ -29,22 +29,21 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
29
29
  // src/index.ts
30
30
  var index_exports = {};
31
31
  __export(index_exports, {
32
- ANTHROPIC_TOOLS: () => ANTHROPIC_TOOLS,
33
- AnthropicToolExecutor: () => AnthropicToolExecutor,
34
32
  BUNDLED_CLIENT_ID: () => BUNDLED_CLIENT_ID,
35
- GITLAB_API_TOOLS: () => GITLAB_API_TOOLS,
33
+ DEFAULT_AI_GATEWAY_URL: () => DEFAULT_AI_GATEWAY_URL,
36
34
  GITLAB_COM_URL: () => GITLAB_COM_URL,
37
35
  GitLabAgenticLanguageModel: () => GitLabAgenticLanguageModel,
38
- GitLabApiToolExecutor: () => GitLabApiToolExecutor,
36
+ GitLabDirectAccessClient: () => GitLabDirectAccessClient,
39
37
  GitLabError: () => GitLabError,
40
38
  GitLabOAuthManager: () => GitLabOAuthManager,
41
39
  GitLabProjectCache: () => GitLabProjectCache,
42
40
  GitLabProjectDetector: () => GitLabProjectDetector,
41
+ MODEL_ID_TO_ANTHROPIC_MODEL: () => MODEL_ID_TO_ANTHROPIC_MODEL,
43
42
  OAUTH_SCOPES: () => OAUTH_SCOPES,
44
43
  TOKEN_EXPIRY_SKEW_MS: () => TOKEN_EXPIRY_SKEW_MS,
45
44
  createGitLab: () => createGitLab,
46
- gitlab: () => gitlab,
47
- isGitLabApiTool: () => isGitLabApiTool
45
+ getAnthropicModelForModelId: () => getAnthropicModelForModelId,
46
+ gitlab: () => gitlab
48
47
  });
49
48
  module.exports = __toCommonJS(index_exports);
50
49
 
@@ -95,14 +94,17 @@ var directAccessTokenSchema = import_zod.z.object({
95
94
  headers: import_zod.z.record(import_zod.z.string()),
96
95
  token: import_zod.z.string()
97
96
  });
97
+ var DEFAULT_AI_GATEWAY_URL = "https://cloud.gitlab.com";
98
98
  var GitLabDirectAccessClient = class {
99
99
  config;
100
100
  fetchFn;
101
+ aiGatewayUrl;
101
102
  cachedToken = null;
102
103
  tokenExpiresAt = 0;
103
104
  constructor(config) {
104
105
  this.config = config;
105
106
  this.fetchFn = config.fetch ?? fetch;
107
+ this.aiGatewayUrl = config.aiGatewayUrl || process.env["GITLAB_AI_GATEWAY_URL"] || DEFAULT_AI_GATEWAY_URL;
106
108
  }
107
109
  /**
108
110
  * Get a direct access token for the Anthropic proxy.
@@ -139,12 +141,23 @@ var GitLabDirectAccessClient = class {
139
141
  return await this.getDirectAccessToken(true);
140
142
  } catch (refreshError) {
141
143
  throw new GitLabError({
142
- message: `Failed to get direct access token: ${response.status} ${response.statusText} - ${errorText}`
144
+ message: `Failed to get direct access token: ${response.status} ${response.statusText} - ${errorText}`,
145
+ statusCode: response.status,
146
+ responseBody: errorText
143
147
  });
144
148
  }
145
149
  }
150
+ if (response.status === 403) {
151
+ throw new GitLabError({
152
+ message: `Access denied to GitLab AI features (${this.config.instanceUrl}). This may indicate that: (1) GitLab Duo is not enabled on this instance, (2) Your account does not have access to AI features, or (3) The third-party agents feature is not available. Original error: ${response.status} ${response.statusText} - ${errorText}`,
153
+ statusCode: response.status,
154
+ responseBody: errorText
155
+ });
156
+ }
146
157
  throw new GitLabError({
147
- message: `Failed to get direct access token: ${response.status} ${response.statusText} - ${errorText}`
158
+ message: `Failed to get direct access token: ${response.status} ${response.statusText} - ${errorText}`,
159
+ statusCode: response.status,
160
+ responseBody: errorText
148
161
  });
149
162
  }
150
163
  const data = await response.json();
@@ -166,7 +179,8 @@ var GitLabDirectAccessClient = class {
166
179
  * Get the Anthropic proxy base URL
167
180
  */
168
181
  getAnthropicProxyUrl() {
169
- return "https://cloud.gitlab.com/ai/v1/proxy/anthropic/";
182
+ const baseUrl = this.aiGatewayUrl.replace(/\/$/, "");
183
+ return `${baseUrl}/ai/v1/proxy/anthropic/`;
170
184
  }
171
185
  /**
172
186
  * Invalidate the cached token
@@ -178,6 +192,8 @@ var GitLabDirectAccessClient = class {
178
192
  };
179
193
 
180
194
  // src/gitlab-agentic-language-model.ts
195
+ var debugLog = (..._args) => {
196
+ };
181
197
  var GitLabAgenticLanguageModel = class {
182
198
  specificationVersion = "v2";
183
199
  modelId;
@@ -193,7 +209,8 @@ var GitLabAgenticLanguageModel = class {
193
209
  getHeaders: config.getHeaders,
194
210
  refreshApiKey: config.refreshApiKey,
195
211
  fetch: config.fetch,
196
- featureFlags: config.featureFlags
212
+ featureFlags: config.featureFlags,
213
+ aiGatewayUrl: config.aiGatewayUrl
197
214
  });
198
215
  }
199
216
  get provider() {
@@ -205,10 +222,19 @@ var GitLabAgenticLanguageModel = class {
205
222
  */
206
223
  async getAnthropicClient(forceRefresh = false) {
207
224
  const tokenData = await this.directAccessClient.getDirectAccessToken(forceRefresh);
225
+ debugLog("[gitlab-ai-provider] Token headers from GitLab:", tokenData.headers);
226
+ debugLog("[gitlab-ai-provider] Proxy URL:", this.directAccessClient.getAnthropicProxyUrl());
227
+ const { "x-api-key": _removed, ...filteredHeaders } = tokenData.headers;
228
+ if (_removed) {
229
+ debugLog(
230
+ "[gitlab-ai-provider] Filtered out x-api-key from headers (using authToken instead)"
231
+ );
232
+ }
208
233
  this.anthropicClient = new import_sdk.default({
234
+ apiKey: null,
209
235
  authToken: tokenData.token,
210
236
  baseURL: this.directAccessClient.getAnthropicProxyUrl(),
211
- defaultHeaders: tokenData.headers
237
+ defaultHeaders: filteredHeaders
212
238
  });
213
239
  return this.anthropicClient;
214
240
  }
@@ -749,6 +775,16 @@ var GitLabOAuthManager = class {
749
775
  }
750
776
  };
751
777
 
778
+ // src/model-mappings.ts
779
+ var MODEL_ID_TO_ANTHROPIC_MODEL = {
780
+ "duo-chat-opus-4-5": "claude-opus-4-5-20251101",
781
+ "duo-chat-sonnet-4-5": "claude-sonnet-4-5-20250929",
782
+ "duo-chat-haiku-4-5": "claude-haiku-4-5-20251001"
783
+ };
784
+ function getAnthropicModelForModelId(modelId) {
785
+ return MODEL_ID_TO_ANTHROPIC_MODEL[modelId];
786
+ }
787
+
752
788
  // src/gitlab-provider.ts
753
789
  var fs = __toESM(require("fs"));
754
790
  var path = __toESM(require("path"));
@@ -895,9 +931,10 @@ function createGitLab(options = {}) {
895
931
  getHeaders,
896
932
  refreshApiKey,
897
933
  fetch: options.fetch,
898
- anthropicModel: agenticOptions?.anthropicModel,
934
+ anthropicModel: agenticOptions?.anthropicModel ?? getAnthropicModelForModelId(modelId),
899
935
  maxTokens: agenticOptions?.maxTokens,
900
- featureFlags
936
+ featureFlags,
937
+ aiGatewayUrl: options.aiGatewayUrl
901
938
  });
902
939
  };
903
940
  const createDefaultModel = (modelId) => {
@@ -923,1196 +960,9 @@ function createGitLab(options = {}) {
923
960
  }
924
961
  var gitlab = createGitLab();
925
962
 
926
- // src/gitlab-api-tools.ts
927
- var GITLAB_API_TOOLS = [
928
- // Merge Request Tools
929
- {
930
- name: "gitlab_get_merge_request",
931
- description: `Get details of a specific merge request by project and MR IID.
932
- Returns: title, description, state, author, assignees, reviewers, labels, diff stats, and discussion notes.`,
933
- input_schema: {
934
- type: "object",
935
- properties: {
936
- project_id: {
937
- type: "string",
938
- description: 'The project ID or URL-encoded path (e.g., "gitlab-org/gitlab" or "123")'
939
- },
940
- mr_iid: {
941
- type: "number",
942
- description: "The internal ID of the merge request within the project"
943
- },
944
- include_changes: {
945
- type: "boolean",
946
- description: "Whether to include the list of changed files (default: false)"
947
- }
948
- },
949
- required: ["project_id", "mr_iid"]
950
- }
951
- },
952
- {
953
- name: "gitlab_list_merge_requests",
954
- description: `List merge requests for a project or search globally.
955
- Can filter by state (opened, closed, merged, all), scope (assigned_to_me, created_by_me), and labels.`,
956
- input_schema: {
957
- type: "object",
958
- properties: {
959
- project_id: {
960
- type: "string",
961
- description: "The project ID or path. If not provided, searches globally."
962
- },
963
- state: {
964
- type: "string",
965
- enum: ["opened", "closed", "merged", "all"],
966
- description: "Filter by MR state (default: opened)"
967
- },
968
- scope: {
969
- type: "string",
970
- enum: ["assigned_to_me", "created_by_me", "all"],
971
- description: "Filter by scope"
972
- },
973
- search: {
974
- type: "string",
975
- description: "Search MRs by title or description"
976
- },
977
- labels: {
978
- type: "string",
979
- description: "Comma-separated list of labels to filter by"
980
- },
981
- limit: {
982
- type: "number",
983
- description: "Maximum number of results (default: 20)"
984
- }
985
- },
986
- required: []
987
- }
988
- },
989
- {
990
- name: "gitlab_get_mr_changes",
991
- description: `Get the file changes (diff) for a merge request.
992
- Returns the list of files changed with their diffs.`,
993
- input_schema: {
994
- type: "object",
995
- properties: {
996
- project_id: {
997
- type: "string",
998
- description: "The project ID or URL-encoded path"
999
- },
1000
- mr_iid: {
1001
- type: "number",
1002
- description: "The internal ID of the merge request"
1003
- }
1004
- },
1005
- required: ["project_id", "mr_iid"]
1006
- }
1007
- },
1008
- {
1009
- name: "gitlab_list_mr_discussions",
1010
- description: `List discussions (comments/threads) on a merge request.
1011
- Returns all discussion threads including resolved status.`,
1012
- input_schema: {
1013
- type: "object",
1014
- properties: {
1015
- project_id: {
1016
- type: "string",
1017
- description: "The project ID or URL-encoded path"
1018
- },
1019
- mr_iid: {
1020
- type: "number",
1021
- description: "The internal ID of the merge request"
1022
- }
1023
- },
1024
- required: ["project_id", "mr_iid"]
1025
- }
1026
- },
1027
- {
1028
- name: "gitlab_create_mr_note",
1029
- description: `Add a comment/note to a merge request.`,
1030
- input_schema: {
1031
- type: "object",
1032
- properties: {
1033
- project_id: {
1034
- type: "string",
1035
- description: "The project ID or URL-encoded path"
1036
- },
1037
- mr_iid: {
1038
- type: "number",
1039
- description: "The internal ID of the merge request"
1040
- },
1041
- body: {
1042
- type: "string",
1043
- description: "The content of the note/comment (supports Markdown)"
1044
- }
1045
- },
1046
- required: ["project_id", "mr_iid", "body"]
1047
- }
1048
- },
1049
- // Issue Tools
1050
- {
1051
- name: "gitlab_get_issue",
1052
- description: `Get details of a specific issue by project and issue IID.
1053
- Returns: title, description, state, author, assignees, labels, milestone, weight, and comments.`,
1054
- input_schema: {
1055
- type: "object",
1056
- properties: {
1057
- project_id: {
1058
- type: "string",
1059
- description: "The project ID or URL-encoded path"
1060
- },
1061
- issue_iid: {
1062
- type: "number",
1063
- description: "The internal ID of the issue within the project"
1064
- }
1065
- },
1066
- required: ["project_id", "issue_iid"]
1067
- }
1068
- },
1069
- {
1070
- name: "gitlab_list_issues",
1071
- description: `List issues for a project or search globally.
1072
- Can filter by state, labels, assignee, milestone.`,
1073
- input_schema: {
1074
- type: "object",
1075
- properties: {
1076
- project_id: {
1077
- type: "string",
1078
- description: "The project ID or path. If not provided, searches globally."
1079
- },
1080
- state: {
1081
- type: "string",
1082
- enum: ["opened", "closed", "all"],
1083
- description: "Filter by issue state (default: opened)"
1084
- },
1085
- scope: {
1086
- type: "string",
1087
- enum: ["assigned_to_me", "created_by_me", "all"],
1088
- description: "Filter by scope"
1089
- },
1090
- search: {
1091
- type: "string",
1092
- description: "Search issues by title or description"
1093
- },
1094
- labels: {
1095
- type: "string",
1096
- description: "Comma-separated list of labels to filter by"
1097
- },
1098
- milestone: {
1099
- type: "string",
1100
- description: "Filter by milestone title"
1101
- },
1102
- limit: {
1103
- type: "number",
1104
- description: "Maximum number of results (default: 20)"
1105
- }
1106
- },
1107
- required: []
1108
- }
1109
- },
1110
- {
1111
- name: "gitlab_create_issue_note",
1112
- description: `Add a comment/note to an issue.`,
1113
- input_schema: {
1114
- type: "object",
1115
- properties: {
1116
- project_id: {
1117
- type: "string",
1118
- description: "The project ID or URL-encoded path"
1119
- },
1120
- issue_iid: {
1121
- type: "number",
1122
- description: "The internal ID of the issue"
1123
- },
1124
- body: {
1125
- type: "string",
1126
- description: "The content of the note/comment (supports Markdown)"
1127
- }
1128
- },
1129
- required: ["project_id", "issue_iid", "body"]
1130
- }
1131
- },
1132
- // Pipeline/CI Tools
1133
- {
1134
- name: "gitlab_list_pipelines",
1135
- description: `List pipelines for a project.
1136
- Can filter by status, ref (branch/tag), username.`,
1137
- input_schema: {
1138
- type: "object",
1139
- properties: {
1140
- project_id: {
1141
- type: "string",
1142
- description: "The project ID or URL-encoded path"
1143
- },
1144
- status: {
1145
- type: "string",
1146
- enum: ["running", "pending", "success", "failed", "canceled", "skipped", "manual"],
1147
- description: "Filter by pipeline status"
1148
- },
1149
- ref: {
1150
- type: "string",
1151
- description: "Filter by branch or tag name"
1152
- },
1153
- limit: {
1154
- type: "number",
1155
- description: "Maximum number of results (default: 20)"
1156
- }
1157
- },
1158
- required: ["project_id"]
1159
- }
1160
- },
1161
- {
1162
- name: "gitlab_get_pipeline",
1163
- description: `Get details of a specific pipeline including its jobs.`,
1164
- input_schema: {
1165
- type: "object",
1166
- properties: {
1167
- project_id: {
1168
- type: "string",
1169
- description: "The project ID or URL-encoded path"
1170
- },
1171
- pipeline_id: {
1172
- type: "number",
1173
- description: "The ID of the pipeline"
1174
- }
1175
- },
1176
- required: ["project_id", "pipeline_id"]
1177
- }
1178
- },
1179
- {
1180
- name: "gitlab_list_pipeline_jobs",
1181
- description: `List jobs for a pipeline, optionally filter by scope (failed, success, etc).`,
1182
- input_schema: {
1183
- type: "object",
1184
- properties: {
1185
- project_id: {
1186
- type: "string",
1187
- description: "The project ID or URL-encoded path"
1188
- },
1189
- pipeline_id: {
1190
- type: "number",
1191
- description: "The ID of the pipeline"
1192
- },
1193
- scope: {
1194
- type: "string",
1195
- enum: [
1196
- "created",
1197
- "pending",
1198
- "running",
1199
- "failed",
1200
- "success",
1201
- "canceled",
1202
- "skipped",
1203
- "manual"
1204
- ],
1205
- description: "Filter jobs by scope/status"
1206
- }
1207
- },
1208
- required: ["project_id", "pipeline_id"]
1209
- }
1210
- },
1211
- {
1212
- name: "gitlab_get_job_log",
1213
- description: `Get the log/trace output of a specific CI job.`,
1214
- input_schema: {
1215
- type: "object",
1216
- properties: {
1217
- project_id: {
1218
- type: "string",
1219
- description: "The project ID or URL-encoded path"
1220
- },
1221
- job_id: {
1222
- type: "number",
1223
- description: "The ID of the job"
1224
- }
1225
- },
1226
- required: ["project_id", "job_id"]
1227
- }
1228
- },
1229
- {
1230
- name: "gitlab_retry_job",
1231
- description: `Retry a failed or canceled CI job.`,
1232
- input_schema: {
1233
- type: "object",
1234
- properties: {
1235
- project_id: {
1236
- type: "string",
1237
- description: "The project ID or URL-encoded path"
1238
- },
1239
- job_id: {
1240
- type: "number",
1241
- description: "The ID of the job to retry"
1242
- }
1243
- },
1244
- required: ["project_id", "job_id"]
1245
- }
1246
- },
1247
- // Repository Tools
1248
- {
1249
- name: "gitlab_get_file",
1250
- description: `Get the contents of a file from a repository.`,
1251
- input_schema: {
1252
- type: "object",
1253
- properties: {
1254
- project_id: {
1255
- type: "string",
1256
- description: "The project ID or URL-encoded path"
1257
- },
1258
- file_path: {
1259
- type: "string",
1260
- description: "Path to the file in the repository"
1261
- },
1262
- ref: {
1263
- type: "string",
1264
- description: "Branch, tag, or commit SHA (default: default branch)"
1265
- }
1266
- },
1267
- required: ["project_id", "file_path"]
1268
- }
1269
- },
1270
- {
1271
- name: "gitlab_list_commits",
1272
- description: `List commits in a repository. Can filter by branch/ref and path.`,
1273
- input_schema: {
1274
- type: "object",
1275
- properties: {
1276
- project_id: {
1277
- type: "string",
1278
- description: "The project ID or URL-encoded path"
1279
- },
1280
- ref: {
1281
- type: "string",
1282
- description: "Branch or tag name"
1283
- },
1284
- path: {
1285
- type: "string",
1286
- description: "File or directory path to filter commits"
1287
- },
1288
- since: {
1289
- type: "string",
1290
- description: "Only commits after this date (ISO 8601 format)"
1291
- },
1292
- until: {
1293
- type: "string",
1294
- description: "Only commits before this date (ISO 8601 format)"
1295
- },
1296
- limit: {
1297
- type: "number",
1298
- description: "Maximum number of results (default: 20)"
1299
- }
1300
- },
1301
- required: ["project_id"]
1302
- }
1303
- },
1304
- {
1305
- name: "gitlab_get_commit_diff",
1306
- description: `Get the diff for a specific commit.`,
1307
- input_schema: {
1308
- type: "object",
1309
- properties: {
1310
- project_id: {
1311
- type: "string",
1312
- description: "The project ID or URL-encoded path"
1313
- },
1314
- sha: {
1315
- type: "string",
1316
- description: "The commit SHA"
1317
- }
1318
- },
1319
- required: ["project_id", "sha"]
1320
- }
1321
- },
1322
- {
1323
- name: "gitlab_list_branches",
1324
- description: `List branches in a repository.`,
1325
- input_schema: {
1326
- type: "object",
1327
- properties: {
1328
- project_id: {
1329
- type: "string",
1330
- description: "The project ID or URL-encoded path"
1331
- },
1332
- search: {
1333
- type: "string",
1334
- description: "Search branches by name"
1335
- }
1336
- },
1337
- required: ["project_id"]
1338
- }
1339
- },
1340
- // Search Tools
1341
- {
1342
- name: "gitlab_search",
1343
- description: `Search across GitLab for various resources.
1344
- Scopes: projects, issues, merge_requests, milestones, users, blobs (code), commits, notes, wiki_blobs`,
1345
- input_schema: {
1346
- type: "object",
1347
- properties: {
1348
- scope: {
1349
- type: "string",
1350
- enum: [
1351
- "projects",
1352
- "issues",
1353
- "merge_requests",
1354
- "milestones",
1355
- "users",
1356
- "blobs",
1357
- "commits",
1358
- "notes",
1359
- "wiki_blobs"
1360
- ],
1361
- description: "The scope of the search"
1362
- },
1363
- search: {
1364
- type: "string",
1365
- description: "The search query"
1366
- },
1367
- project_id: {
1368
- type: "string",
1369
- description: "Limit search to a specific project (optional)"
1370
- },
1371
- limit: {
1372
- type: "number",
1373
- description: "Maximum number of results (default: 20)"
1374
- }
1375
- },
1376
- required: ["scope", "search"]
1377
- }
1378
- },
1379
- // Project Tools
1380
- {
1381
- name: "gitlab_get_project",
1382
- description: `Get details of a specific project.`,
1383
- input_schema: {
1384
- type: "object",
1385
- properties: {
1386
- project_id: {
1387
- type: "string",
1388
- description: 'The project ID or URL-encoded path (e.g., "gitlab-org/gitlab")'
1389
- }
1390
- },
1391
- required: ["project_id"]
1392
- }
1393
- },
1394
- {
1395
- name: "gitlab_list_project_members",
1396
- description: `List members of a project.`,
1397
- input_schema: {
1398
- type: "object",
1399
- properties: {
1400
- project_id: {
1401
- type: "string",
1402
- description: "The project ID or URL-encoded path"
1403
- }
1404
- },
1405
- required: ["project_id"]
1406
- }
1407
- }
1408
- ];
1409
- var GitLabApiToolExecutor = class {
1410
- config;
1411
- constructor(config) {
1412
- this.config = config;
1413
- }
1414
- get headers() {
1415
- return {
1416
- Authorization: `Bearer ${this.config.token}`,
1417
- "Content-Type": "application/json"
1418
- };
1419
- }
1420
- async fetchApi(method, path4, body) {
1421
- const url = `${this.config.instanceUrl}/api/v4${path4}`;
1422
- const fetchFn = this.config.fetch || fetch;
1423
- const response = await fetchFn(url, {
1424
- method,
1425
- headers: this.headers,
1426
- body: body ? JSON.stringify(body) : void 0
1427
- });
1428
- if (!response.ok) {
1429
- const errorText = await response.text();
1430
- throw new Error(`GitLab API error ${response.status}: ${errorText}`);
1431
- }
1432
- const text = await response.text();
1433
- if (!text) {
1434
- return {};
1435
- }
1436
- return JSON.parse(text);
1437
- }
1438
- encodeProjectId(projectId) {
1439
- if (projectId.includes("/")) {
1440
- return encodeURIComponent(projectId);
1441
- }
1442
- return projectId;
1443
- }
1444
- /**
1445
- * Execute a GitLab API tool by name
1446
- */
1447
- async execute(toolName, input) {
1448
- try {
1449
- switch (toolName) {
1450
- // Merge Request tools
1451
- case "gitlab_get_merge_request":
1452
- return this.getMergeRequest(input);
1453
- case "gitlab_list_merge_requests":
1454
- return this.listMergeRequests(input);
1455
- case "gitlab_get_mr_changes":
1456
- return this.getMrChanges(input);
1457
- case "gitlab_list_mr_discussions":
1458
- return this.listMrDiscussions(input);
1459
- case "gitlab_create_mr_note":
1460
- return this.createMrNote(input);
1461
- // Issue tools
1462
- case "gitlab_get_issue":
1463
- return this.getIssue(input);
1464
- case "gitlab_list_issues":
1465
- return this.listIssues(input);
1466
- case "gitlab_create_issue_note":
1467
- return this.createIssueNote(input);
1468
- // Pipeline tools
1469
- case "gitlab_list_pipelines":
1470
- return this.listPipelines(input);
1471
- case "gitlab_get_pipeline":
1472
- return this.getPipeline(input);
1473
- case "gitlab_list_pipeline_jobs":
1474
- return this.listPipelineJobs(input);
1475
- case "gitlab_get_job_log":
1476
- return this.getJobLog(input);
1477
- case "gitlab_retry_job":
1478
- return this.retryJob(input);
1479
- // Repository tools
1480
- case "gitlab_get_file":
1481
- return this.getFile(input);
1482
- case "gitlab_list_commits":
1483
- return this.listCommits(input);
1484
- case "gitlab_get_commit_diff":
1485
- return this.getCommitDiff(input);
1486
- case "gitlab_list_branches":
1487
- return this.listBranches(input);
1488
- // Search tools
1489
- case "gitlab_search":
1490
- return this.search(input);
1491
- // Project tools
1492
- case "gitlab_get_project":
1493
- return this.getProject(input);
1494
- case "gitlab_list_project_members":
1495
- return this.listProjectMembers(input);
1496
- default:
1497
- return { result: "", error: `Unknown GitLab tool: ${toolName}` };
1498
- }
1499
- } catch (error) {
1500
- return {
1501
- result: "",
1502
- error: error instanceof Error ? error.message : String(error)
1503
- };
1504
- }
1505
- }
1506
- // ========== Merge Request Tools ==========
1507
- async getMergeRequest(input) {
1508
- const projectId = this.encodeProjectId(input.project_id);
1509
- const mrIid = input.mr_iid;
1510
- const includeChanges = input.include_changes;
1511
- let path4 = `/projects/${projectId}/merge_requests/${mrIid}`;
1512
- if (includeChanges) {
1513
- path4 += "?include_diverged_commits_count=true";
1514
- }
1515
- const mr = await this.fetchApi("GET", path4);
1516
- return { result: JSON.stringify(mr, null, 2) };
1517
- }
1518
- async listMergeRequests(input) {
1519
- const params = new URLSearchParams();
1520
- params.set("per_page", String(input.limit || 20));
1521
- if (input.state) params.set("state", input.state);
1522
- if (input.scope) params.set("scope", input.scope);
1523
- if (input.search) params.set("search", input.search);
1524
- if (input.labels) params.set("labels", input.labels);
1525
- let path4;
1526
- if (input.project_id) {
1527
- const projectId = this.encodeProjectId(input.project_id);
1528
- path4 = `/projects/${projectId}/merge_requests?${params}`;
1529
- } else {
1530
- path4 = `/merge_requests?${params}`;
1531
- }
1532
- const mrs = await this.fetchApi("GET", path4);
1533
- return { result: JSON.stringify(mrs, null, 2) };
1534
- }
1535
- async getMrChanges(input) {
1536
- const projectId = this.encodeProjectId(input.project_id);
1537
- const mrIid = input.mr_iid;
1538
- const changes = await this.fetchApi(
1539
- "GET",
1540
- `/projects/${projectId}/merge_requests/${mrIid}/changes`
1541
- );
1542
- return { result: JSON.stringify(changes, null, 2) };
1543
- }
1544
- async listMrDiscussions(input) {
1545
- const projectId = this.encodeProjectId(input.project_id);
1546
- const mrIid = input.mr_iid;
1547
- const discussions = await this.fetchApi(
1548
- "GET",
1549
- `/projects/${projectId}/merge_requests/${mrIid}/discussions`
1550
- );
1551
- return { result: JSON.stringify(discussions, null, 2) };
1552
- }
1553
- async createMrNote(input) {
1554
- const projectId = this.encodeProjectId(input.project_id);
1555
- const mrIid = input.mr_iid;
1556
- const body = input.body;
1557
- const note = await this.fetchApi(
1558
- "POST",
1559
- `/projects/${projectId}/merge_requests/${mrIid}/notes`,
1560
- { body }
1561
- );
1562
- return { result: JSON.stringify(note, null, 2) };
1563
- }
1564
- // ========== Issue Tools ==========
1565
- async getIssue(input) {
1566
- const projectId = this.encodeProjectId(input.project_id);
1567
- const issueIid = input.issue_iid;
1568
- const issue = await this.fetchApi(
1569
- "GET",
1570
- `/projects/${projectId}/issues/${issueIid}`
1571
- );
1572
- return { result: JSON.stringify(issue, null, 2) };
1573
- }
1574
- async listIssues(input) {
1575
- const params = new URLSearchParams();
1576
- params.set("per_page", String(input.limit || 20));
1577
- if (input.state) params.set("state", input.state);
1578
- if (input.scope) params.set("scope", input.scope);
1579
- if (input.search) params.set("search", input.search);
1580
- if (input.labels) params.set("labels", input.labels);
1581
- if (input.milestone) params.set("milestone", input.milestone);
1582
- let path4;
1583
- if (input.project_id) {
1584
- const projectId = this.encodeProjectId(input.project_id);
1585
- path4 = `/projects/${projectId}/issues?${params}`;
1586
- } else {
1587
- path4 = `/issues?${params}`;
1588
- }
1589
- const issues = await this.fetchApi("GET", path4);
1590
- return { result: JSON.stringify(issues, null, 2) };
1591
- }
1592
- async createIssueNote(input) {
1593
- const projectId = this.encodeProjectId(input.project_id);
1594
- const issueIid = input.issue_iid;
1595
- const body = input.body;
1596
- const note = await this.fetchApi(
1597
- "POST",
1598
- `/projects/${projectId}/issues/${issueIid}/notes`,
1599
- { body }
1600
- );
1601
- return { result: JSON.stringify(note, null, 2) };
1602
- }
1603
- // ========== Pipeline Tools ==========
1604
- async listPipelines(input) {
1605
- const projectId = this.encodeProjectId(input.project_id);
1606
- const params = new URLSearchParams();
1607
- params.set("per_page", String(input.limit || 20));
1608
- if (input.status) params.set("status", input.status);
1609
- if (input.ref) params.set("ref", input.ref);
1610
- const pipelines = await this.fetchApi(
1611
- "GET",
1612
- `/projects/${projectId}/pipelines?${params}`
1613
- );
1614
- return { result: JSON.stringify(pipelines, null, 2) };
1615
- }
1616
- async getPipeline(input) {
1617
- const projectId = this.encodeProjectId(input.project_id);
1618
- const pipelineId = input.pipeline_id;
1619
- const pipeline = await this.fetchApi(
1620
- "GET",
1621
- `/projects/${projectId}/pipelines/${pipelineId}`
1622
- );
1623
- return { result: JSON.stringify(pipeline, null, 2) };
1624
- }
1625
- async listPipelineJobs(input) {
1626
- const projectId = this.encodeProjectId(input.project_id);
1627
- const pipelineId = input.pipeline_id;
1628
- const params = new URLSearchParams();
1629
- if (input.scope) params.set("scope[]", input.scope);
1630
- const jobs = await this.fetchApi(
1631
- "GET",
1632
- `/projects/${projectId}/pipelines/${pipelineId}/jobs?${params}`
1633
- );
1634
- return { result: JSON.stringify(jobs, null, 2) };
1635
- }
1636
- async getJobLog(input) {
1637
- const projectId = this.encodeProjectId(input.project_id);
1638
- const jobId = input.job_id;
1639
- const url = `${this.config.instanceUrl}/api/v4/projects/${projectId}/jobs/${jobId}/trace`;
1640
- const fetchFn = this.config.fetch || fetch;
1641
- const response = await fetchFn(url, {
1642
- method: "GET",
1643
- headers: this.headers
1644
- });
1645
- if (!response.ok) {
1646
- const errorText = await response.text();
1647
- throw new Error(`GitLab API error ${response.status}: ${errorText}`);
1648
- }
1649
- const log = await response.text();
1650
- const maxLength = 5e4;
1651
- if (log.length > maxLength) {
1652
- return {
1653
- result: `[Log truncated, showing last ${maxLength} characters]
1654
-
1655
- ${log.slice(-maxLength)}`
1656
- };
1657
- }
1658
- return { result: log };
1659
- }
1660
- async retryJob(input) {
1661
- const projectId = this.encodeProjectId(input.project_id);
1662
- const jobId = input.job_id;
1663
- const job = await this.fetchApi(
1664
- "POST",
1665
- `/projects/${projectId}/jobs/${jobId}/retry`
1666
- );
1667
- return { result: JSON.stringify(job, null, 2) };
1668
- }
1669
- // ========== Repository Tools ==========
1670
- async getFile(input) {
1671
- const projectId = this.encodeProjectId(input.project_id);
1672
- const filePath = encodeURIComponent(input.file_path);
1673
- const ref = input.ref || "HEAD";
1674
- const file = await this.fetchApi(
1675
- "GET",
1676
- `/projects/${projectId}/repository/files/${filePath}?ref=${encodeURIComponent(ref)}`
1677
- );
1678
- if (file.encoding === "base64") {
1679
- const decoded = Buffer.from(file.content, "base64").toString("utf-8");
1680
- return { result: decoded };
1681
- }
1682
- return { result: file.content };
1683
- }
1684
- async listCommits(input) {
1685
- const projectId = this.encodeProjectId(input.project_id);
1686
- const params = new URLSearchParams();
1687
- params.set("per_page", String(input.limit || 20));
1688
- if (input.ref) params.set("ref_name", input.ref);
1689
- if (input.path) params.set("path", input.path);
1690
- if (input.since) params.set("since", input.since);
1691
- if (input.until) params.set("until", input.until);
1692
- const commits = await this.fetchApi(
1693
- "GET",
1694
- `/projects/${projectId}/repository/commits?${params}`
1695
- );
1696
- return { result: JSON.stringify(commits, null, 2) };
1697
- }
1698
- async getCommitDiff(input) {
1699
- const projectId = this.encodeProjectId(input.project_id);
1700
- const sha = input.sha;
1701
- const diff = await this.fetchApi(
1702
- "GET",
1703
- `/projects/${projectId}/repository/commits/${sha}/diff`
1704
- );
1705
- return { result: JSON.stringify(diff, null, 2) };
1706
- }
1707
- async listBranches(input) {
1708
- const projectId = this.encodeProjectId(input.project_id);
1709
- const params = new URLSearchParams();
1710
- if (input.search) params.set("search", input.search);
1711
- const branches = await this.fetchApi(
1712
- "GET",
1713
- `/projects/${projectId}/repository/branches?${params}`
1714
- );
1715
- return { result: JSON.stringify(branches, null, 2) };
1716
- }
1717
- // ========== Search Tools ==========
1718
- async search(input) {
1719
- const scope = input.scope;
1720
- const searchQuery = input.search;
1721
- const params = new URLSearchParams();
1722
- params.set("scope", scope);
1723
- params.set("search", searchQuery);
1724
- params.set("per_page", String(input.limit || 20));
1725
- let path4;
1726
- if (input.project_id) {
1727
- const projectId = this.encodeProjectId(input.project_id);
1728
- path4 = `/projects/${projectId}/search?${params}`;
1729
- } else {
1730
- path4 = `/search?${params}`;
1731
- }
1732
- const results = await this.fetchApi("GET", path4);
1733
- return { result: JSON.stringify(results, null, 2) };
1734
- }
1735
- // ========== Project Tools ==========
1736
- async getProject(input) {
1737
- const projectId = this.encodeProjectId(input.project_id);
1738
- const project = await this.fetchApi("GET", `/projects/${projectId}`);
1739
- return { result: JSON.stringify(project, null, 2) };
1740
- }
1741
- async listProjectMembers(input) {
1742
- const projectId = this.encodeProjectId(input.project_id);
1743
- const members = await this.fetchApi(
1744
- "GET",
1745
- `/projects/${projectId}/members`
1746
- );
1747
- return { result: JSON.stringify(members, null, 2) };
1748
- }
1749
- };
1750
- function isGitLabApiTool(toolName) {
1751
- return toolName.startsWith("gitlab_");
1752
- }
1753
-
1754
- // src/gitlab-anthropic-tools.ts
1755
- var fs2 = __toESM(require("fs/promises"));
1756
- var path2 = __toESM(require("path"));
1757
- var import_child_process = require("child_process");
1758
- var ANTHROPIC_TOOLS = [
1759
- {
1760
- name: "list_dir",
1761
- description: `List directory contents. Shows files and subdirectories relative to the working directory.`,
1762
- input_schema: {
1763
- type: "object",
1764
- properties: {
1765
- directory: {
1766
- type: "string",
1767
- description: "Directory path relative to the working directory"
1768
- }
1769
- },
1770
- required: ["directory"]
1771
- }
1772
- },
1773
- {
1774
- name: "read_file",
1775
- description: `Read the contents of a file.`,
1776
- input_schema: {
1777
- type: "object",
1778
- properties: {
1779
- file_path: {
1780
- type: "string",
1781
- description: "The file path to read"
1782
- }
1783
- },
1784
- required: ["file_path"]
1785
- }
1786
- },
1787
- {
1788
- name: "create_file_with_contents",
1789
- description: `Create and write contents to a file.`,
1790
- input_schema: {
1791
- type: "object",
1792
- properties: {
1793
- file_path: {
1794
- type: "string",
1795
- description: "The file path to write to"
1796
- },
1797
- contents: {
1798
- type: "string",
1799
- description: "The contents to write"
1800
- }
1801
- },
1802
- required: ["file_path", "contents"]
1803
- }
1804
- },
1805
- {
1806
- name: "edit_file",
1807
- description: `Edit an existing file by replacing a string with a new string.`,
1808
- input_schema: {
1809
- type: "object",
1810
- properties: {
1811
- file_path: {
1812
- type: "string",
1813
- description: "The path of the file to edit"
1814
- },
1815
- old_str: {
1816
- type: "string",
1817
- description: "The string to replace (include context for uniqueness)"
1818
- },
1819
- new_str: {
1820
- type: "string",
1821
- description: "The new string value"
1822
- }
1823
- },
1824
- required: ["file_path", "old_str", "new_str"]
1825
- }
1826
- },
1827
- {
1828
- name: "find_files",
1829
- description: `Find files by name pattern. Uses glob-like matching.`,
1830
- input_schema: {
1831
- type: "object",
1832
- properties: {
1833
- name_pattern: {
1834
- type: "string",
1835
- description: 'The pattern to search for (e.g., "*.py", "test_*.js")'
1836
- }
1837
- },
1838
- required: ["name_pattern"]
1839
- }
1840
- },
1841
- {
1842
- name: "mkdir",
1843
- description: `Create a new directory.`,
1844
- input_schema: {
1845
- type: "object",
1846
- properties: {
1847
- directory_path: {
1848
- type: "string",
1849
- description: "The directory path to create"
1850
- }
1851
- },
1852
- required: ["directory_path"]
1853
- }
1854
- },
1855
- {
1856
- name: "grep",
1857
- description: `Search for text patterns within files.`,
1858
- input_schema: {
1859
- type: "object",
1860
- properties: {
1861
- pattern: {
1862
- type: "string",
1863
- description: "The text pattern to search for"
1864
- },
1865
- search_directory: {
1866
- type: "string",
1867
- description: 'The directory to search in (default: ".")'
1868
- },
1869
- case_insensitive: {
1870
- type: "boolean",
1871
- description: "Whether to ignore case (default: false)"
1872
- }
1873
- },
1874
- required: ["pattern"]
1875
- }
1876
- },
1877
- {
1878
- name: "run_command",
1879
- description: `Run a shell command. Note: git commands should use run_git_command instead.`,
1880
- input_schema: {
1881
- type: "object",
1882
- properties: {
1883
- program: {
1884
- type: "string",
1885
- description: 'The program to execute (e.g., "npm", "python")'
1886
- },
1887
- args: {
1888
- type: "string",
1889
- description: "Arguments as a single string"
1890
- }
1891
- },
1892
- required: ["program"]
1893
- }
1894
- },
1895
- {
1896
- name: "run_git_command",
1897
- description: `Run a git command in the repository.`,
1898
- input_schema: {
1899
- type: "object",
1900
- properties: {
1901
- command: {
1902
- type: "string",
1903
- description: 'Git command (e.g., "status", "log", "diff")'
1904
- },
1905
- args: {
1906
- type: "string",
1907
- description: "Git command arguments"
1908
- }
1909
- },
1910
- required: ["command"]
1911
- }
1912
- }
1913
- ];
1914
- var AnthropicToolExecutor = class {
1915
- workingDirectory;
1916
- constructor(workingDirectory) {
1917
- this.workingDirectory = workingDirectory;
1918
- }
1919
- /**
1920
- * Execute a tool by name with given input
1921
- */
1922
- async execute(toolName, input) {
1923
- try {
1924
- switch (toolName) {
1925
- case "list_dir":
1926
- return this.listDir(input.directory);
1927
- case "read_file":
1928
- return this.readFile(input.file_path);
1929
- case "create_file_with_contents":
1930
- return this.writeFile(input.file_path, input.contents);
1931
- case "edit_file":
1932
- return this.editFile(
1933
- input.file_path,
1934
- input.old_str,
1935
- input.new_str
1936
- );
1937
- case "find_files":
1938
- return this.findFiles(input.name_pattern);
1939
- case "mkdir":
1940
- return this.mkdir(input.directory_path);
1941
- case "grep":
1942
- return this.grep(
1943
- input.pattern,
1944
- input.search_directory,
1945
- input.case_insensitive
1946
- );
1947
- case "run_command":
1948
- return this.runCommand(input.program, input.args);
1949
- case "run_git_command":
1950
- return this.runGitCommand(input.command, input.args);
1951
- default:
1952
- return { result: "", error: `Unknown tool: ${toolName}` };
1953
- }
1954
- } catch (error) {
1955
- return {
1956
- result: "",
1957
- error: error instanceof Error ? error.message : String(error)
1958
- };
1959
- }
1960
- }
1961
- resolvePath(filePath) {
1962
- if (path2.isAbsolute(filePath)) {
1963
- return filePath;
1964
- }
1965
- return path2.resolve(this.workingDirectory, filePath);
1966
- }
1967
- async listDir(directory) {
1968
- const dirPath = this.resolvePath(directory || ".");
1969
- const entries = await fs2.readdir(dirPath, { withFileTypes: true });
1970
- const result = entries.map((entry) => {
1971
- const type = entry.isDirectory() ? "d" : "-";
1972
- return `${type} ${entry.name}`;
1973
- }).join("\n");
1974
- return { result };
1975
- }
1976
- async readFile(filePath) {
1977
- const fullPath = this.resolvePath(filePath);
1978
- const content = await fs2.readFile(fullPath, "utf-8");
1979
- return { result: content };
1980
- }
1981
- async writeFile(filePath, contents) {
1982
- const fullPath = this.resolvePath(filePath);
1983
- await fs2.mkdir(path2.dirname(fullPath), { recursive: true });
1984
- await fs2.writeFile(fullPath, contents, "utf-8");
1985
- return { result: `File written successfully: ${filePath}` };
1986
- }
1987
- async editFile(filePath, oldStr, newStr) {
1988
- const fullPath = this.resolvePath(filePath);
1989
- const content = await fs2.readFile(fullPath, "utf-8");
1990
- if (!content.includes(oldStr)) {
1991
- return { result: "", error: `String not found in file: "${oldStr.substring(0, 50)}..."` };
1992
- }
1993
- const newContent = content.replace(oldStr, newStr);
1994
- await fs2.writeFile(fullPath, newContent, "utf-8");
1995
- return { result: `File edited successfully: ${filePath}` };
1996
- }
1997
- async findFiles(namePattern) {
1998
- const results = [];
1999
- const regex = new RegExp("^" + namePattern.replace(/\*/g, ".*").replace(/\?/g, ".") + "$");
2000
- const search = async (dir, relativePath = "") => {
2001
- try {
2002
- const entries = await fs2.readdir(dir, { withFileTypes: true });
2003
- for (const entry of entries) {
2004
- const entryRelativePath = relativePath ? `${relativePath}/${entry.name}` : entry.name;
2005
- if (entry.isDirectory()) {
2006
- if (!["node_modules", ".git", "dist", "build", "__pycache__"].includes(entry.name)) {
2007
- await search(path2.join(dir, entry.name), entryRelativePath);
2008
- }
2009
- } else if (regex.test(entry.name)) {
2010
- results.push(entryRelativePath);
2011
- }
2012
- }
2013
- } catch {
2014
- }
2015
- };
2016
- await search(this.workingDirectory);
2017
- return { result: results.join("\n") || "No files found" };
2018
- }
2019
- async mkdir(directoryPath) {
2020
- const fullPath = this.resolvePath(directoryPath);
2021
- await fs2.mkdir(fullPath, { recursive: true });
2022
- return { result: `Directory created: ${directoryPath}` };
2023
- }
2024
- async grep(pattern, searchDirectory, caseInsensitive) {
2025
- const results = [];
2026
- const flags = caseInsensitive ? "gi" : "g";
2027
- const regex = new RegExp(pattern, flags);
2028
- const searchDir = this.resolvePath(searchDirectory || ".");
2029
- const search = async (dir, relativePath = "") => {
2030
- try {
2031
- const entries = await fs2.readdir(dir, { withFileTypes: true });
2032
- for (const entry of entries) {
2033
- const entryRelativePath = relativePath ? `${relativePath}/${entry.name}` : entry.name;
2034
- const fullPath = path2.join(dir, entry.name);
2035
- if (entry.isDirectory()) {
2036
- if (!["node_modules", ".git", "dist", "build", "__pycache__"].includes(entry.name)) {
2037
- await search(fullPath, entryRelativePath);
2038
- }
2039
- } else {
2040
- try {
2041
- const content = await fs2.readFile(fullPath, "utf-8");
2042
- const lines = content.split("\n");
2043
- for (let i = 0; i < lines.length; i++) {
2044
- if (regex.test(lines[i])) {
2045
- results.push(`${entryRelativePath}:${i + 1}: ${lines[i].trim()}`);
2046
- }
2047
- }
2048
- } catch {
2049
- }
2050
- }
2051
- }
2052
- } catch {
2053
- }
2054
- };
2055
- await search(searchDir);
2056
- return { result: results.slice(0, 100).join("\n") || "No matches found" };
2057
- }
2058
- runCommand(program, args) {
2059
- if (program === "git") {
2060
- return Promise.resolve({
2061
- result: "",
2062
- error: "Use run_git_command for git operations"
2063
- });
2064
- }
2065
- const parsedArgs = args ? args.match(/(?:[^\s"]+|"[^"]*")+/g) || [] : [];
2066
- const cleanedArgs = parsedArgs.map((arg) => arg.replace(/^"(.*)"$/, "$1"));
2067
- return this.executeCommand(program, cleanedArgs);
2068
- }
2069
- runGitCommand(command, args) {
2070
- const gitArgs = [command];
2071
- if (args) {
2072
- const parsedArgs = args.match(/(?:[^\s"]+|"[^"]*")+/g) || [];
2073
- gitArgs.push(...parsedArgs.map((arg) => arg.replace(/^"(.*)"$/, "$1")));
2074
- }
2075
- return this.executeCommand("git", gitArgs);
2076
- }
2077
- executeCommand(program, args) {
2078
- return new Promise((resolve3) => {
2079
- const child = (0, import_child_process.spawn)(program, args, {
2080
- cwd: this.workingDirectory,
2081
- timeout: 3e4
2082
- });
2083
- let stdout = "";
2084
- let stderr = "";
2085
- child.stdout?.on("data", (data) => {
2086
- stdout += data.toString();
2087
- });
2088
- child.stderr?.on("data", (data) => {
2089
- stderr += data.toString();
2090
- });
2091
- child.on("error", (error) => {
2092
- resolve3({
2093
- result: "",
2094
- error: `Command failed: ${error.message}`
2095
- });
2096
- });
2097
- child.on("close", (exitCode) => {
2098
- if (exitCode !== 0 && stderr) {
2099
- resolve3({
2100
- result: stdout,
2101
- error: stderr
2102
- });
2103
- } else {
2104
- resolve3({
2105
- result: stdout || stderr || `Command completed with exit code ${exitCode}`
2106
- });
2107
- }
2108
- });
2109
- });
2110
- }
2111
- };
2112
-
2113
963
  // src/gitlab-project-detector.ts
2114
- var import_child_process2 = require("child_process");
2115
- var path3 = __toESM(require("path"));
964
+ var import_child_process = require("child_process");
965
+ var path2 = __toESM(require("path"));
2116
966
 
2117
967
  // src/gitlab-project-cache.ts
2118
968
  var GitLabProjectCache = class {
@@ -2195,7 +1045,7 @@ var GitLabProjectCache = class {
2195
1045
  };
2196
1046
 
2197
1047
  // src/gitlab-project-detector.ts
2198
- var debugLog = (..._args) => {
1048
+ var debugLog2 = (..._args) => {
2199
1049
  };
2200
1050
  var GitLabProjectDetector = class {
2201
1051
  config;
@@ -2218,41 +1068,41 @@ var GitLabProjectDetector = class {
2218
1068
  * @returns The detected project or null if detection fails
2219
1069
  */
2220
1070
  async detectProject(workingDirectory, remoteName = "origin") {
2221
- const cacheKey = path3.resolve(workingDirectory);
1071
+ const cacheKey = path2.resolve(workingDirectory);
2222
1072
  const cached = this.cache.get(cacheKey);
2223
1073
  if (cached) {
2224
1074
  return cached;
2225
1075
  }
2226
1076
  try {
2227
- debugLog(`[GitLabProjectDetector] Getting git remote URL from: ${workingDirectory}`);
1077
+ debugLog2(`[GitLabProjectDetector] Getting git remote URL from: ${workingDirectory}`);
2228
1078
  const remoteUrl = await this.getGitRemoteUrl(workingDirectory, remoteName);
2229
1079
  if (!remoteUrl) {
2230
- debugLog(`[GitLabProjectDetector] No git remote URL found`);
1080
+ debugLog2(`[GitLabProjectDetector] No git remote URL found`);
2231
1081
  return null;
2232
1082
  }
2233
- debugLog(`[GitLabProjectDetector] Git remote URL: ${remoteUrl}`);
2234
- debugLog(
1083
+ debugLog2(`[GitLabProjectDetector] Git remote URL: ${remoteUrl}`);
1084
+ debugLog2(
2235
1085
  `[GitLabProjectDetector] Parsing project path from URL (instance: ${this.config.instanceUrl})`
2236
1086
  );
2237
1087
  const projectPath = this.parseGitRemoteUrl(remoteUrl, this.config.instanceUrl);
2238
1088
  if (!projectPath) {
2239
- debugLog(
1089
+ debugLog2(
2240
1090
  `[GitLabProjectDetector] Could not parse project path from URL (remote doesn't match instance)`
2241
1091
  );
2242
1092
  return null;
2243
1093
  }
2244
- debugLog(`[GitLabProjectDetector] Parsed project path: ${projectPath}`);
2245
- debugLog(`[GitLabProjectDetector] Fetching project from GitLab API: ${projectPath}`);
1094
+ debugLog2(`[GitLabProjectDetector] Parsed project path: ${projectPath}`);
1095
+ debugLog2(`[GitLabProjectDetector] Fetching project from GitLab API: ${projectPath}`);
2246
1096
  const project = await this.getProjectByPath(projectPath);
2247
- debugLog(`[GitLabProjectDetector] \u2713 Project fetched successfully:`, project);
1097
+ debugLog2(`[GitLabProjectDetector] \u2713 Project fetched successfully:`, project);
2248
1098
  this.cache.set(cacheKey, project);
2249
1099
  return project;
2250
1100
  } catch (error) {
2251
1101
  if (error instanceof GitLabError) {
2252
- debugLog(`[GitLabProjectDetector] GitLab API error:`, error.message || error);
1102
+ debugLog2(`[GitLabProjectDetector] GitLab API error:`, error.message || error);
2253
1103
  return null;
2254
1104
  }
2255
- debugLog(`[GitLabProjectDetector] Unexpected error:`, error);
1105
+ debugLog2(`[GitLabProjectDetector] Unexpected error:`, error);
2256
1106
  console.warn(`Failed to auto-detect GitLab project: ${error}`);
2257
1107
  return null;
2258
1108
  }
@@ -2303,8 +1153,8 @@ var GitLabProjectDetector = class {
2303
1153
  * @returns The remote URL or null if not found
2304
1154
  */
2305
1155
  async getGitRemoteUrl(workingDirectory, remoteName = "origin") {
2306
- return new Promise((resolve3) => {
2307
- const child = (0, import_child_process2.spawn)("git", ["config", "--get", `remote.${remoteName}.url`], {
1156
+ return new Promise((resolve2) => {
1157
+ const child = (0, import_child_process.spawn)("git", ["config", "--get", `remote.${remoteName}.url`], {
2308
1158
  cwd: workingDirectory,
2309
1159
  timeout: this.config.gitTimeout
2310
1160
  });
@@ -2318,13 +1168,13 @@ var GitLabProjectDetector = class {
2318
1168
  });
2319
1169
  child.on("close", (exitCode) => {
2320
1170
  if (exitCode === 0 && stdout.trim()) {
2321
- resolve3(stdout.trim());
1171
+ resolve2(stdout.trim());
2322
1172
  } else {
2323
- resolve3(null);
1173
+ resolve2(null);
2324
1174
  }
2325
1175
  });
2326
1176
  child.on("error", () => {
2327
- resolve3(null);
1177
+ resolve2(null);
2328
1178
  });
2329
1179
  });
2330
1180
  }
@@ -2381,21 +1231,20 @@ var GitLabProjectDetector = class {
2381
1231
  };
2382
1232
  // Annotate the CommonJS export names for ESM import in node:
2383
1233
  0 && (module.exports = {
2384
- ANTHROPIC_TOOLS,
2385
- AnthropicToolExecutor,
2386
1234
  BUNDLED_CLIENT_ID,
2387
- GITLAB_API_TOOLS,
1235
+ DEFAULT_AI_GATEWAY_URL,
2388
1236
  GITLAB_COM_URL,
2389
1237
  GitLabAgenticLanguageModel,
2390
- GitLabApiToolExecutor,
1238
+ GitLabDirectAccessClient,
2391
1239
  GitLabError,
2392
1240
  GitLabOAuthManager,
2393
1241
  GitLabProjectCache,
2394
1242
  GitLabProjectDetector,
1243
+ MODEL_ID_TO_ANTHROPIC_MODEL,
2395
1244
  OAUTH_SCOPES,
2396
1245
  TOKEN_EXPIRY_SKEW_MS,
2397
1246
  createGitLab,
2398
- gitlab,
2399
- isGitLabApiTool
1247
+ getAnthropicModelForModelId,
1248
+ gitlab
2400
1249
  });
2401
1250
  //# sourceMappingURL=index.js.map