@debugbundle/mcp 0.1.1 → 0.1.3
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/main.cjs +870 -153
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -14551,7 +14551,8 @@ function createAlertApi(client) {
|
|
|
14551
14551
|
const body = {
|
|
14552
14552
|
project_id: input.projectId,
|
|
14553
14553
|
channel: input.channel,
|
|
14554
|
-
condition_type: input.conditionType
|
|
14554
|
+
condition_type: input.conditionType,
|
|
14555
|
+
config: input.config
|
|
14555
14556
|
};
|
|
14556
14557
|
if (input.serviceId !== void 0) {
|
|
14557
14558
|
body.service_id = input.serviceId;
|
|
@@ -14559,9 +14560,6 @@ function createAlertApi(client) {
|
|
|
14559
14560
|
if (input.severityMin !== void 0) {
|
|
14560
14561
|
body.severity_min = input.severityMin;
|
|
14561
14562
|
}
|
|
14562
|
-
if (input.config !== void 0) {
|
|
14563
|
-
body.config = input.config;
|
|
14564
|
-
}
|
|
14565
14563
|
if (input.isEnabled !== void 0) {
|
|
14566
14564
|
body.is_enabled = input.isEnabled;
|
|
14567
14565
|
}
|
|
@@ -15200,7 +15198,7 @@ function createProjectManagementApi(client) {
|
|
|
15200
15198
|
|
|
15201
15199
|
// ../../packages/retrieval-client/src/index.ts
|
|
15202
15200
|
var IncidentReasonSchema = external_exports.object({
|
|
15203
|
-
kind: external_exports.enum(["backend_exception", "frontend_exception", "
|
|
15201
|
+
kind: external_exports.enum(["backend_exception", "frontend_exception", "request_failure", "error_log"]),
|
|
15204
15202
|
description: external_exports.string(),
|
|
15205
15203
|
event_type: external_exports.enum(["backend_exception", "frontend_exception", "request_event", "log_event"]),
|
|
15206
15204
|
event_class: external_exports.literal("incident_signal"),
|
|
@@ -15522,6 +15520,121 @@ function createRetrievalApi(client) {
|
|
|
15522
15520
|
};
|
|
15523
15521
|
}
|
|
15524
15522
|
|
|
15523
|
+
// ../../packages/slack-client/src/index.ts
|
|
15524
|
+
var SlackDestinationRecordSchema = external_exports.object({
|
|
15525
|
+
slack_destination_id: external_exports.string(),
|
|
15526
|
+
organization_id: external_exports.string(),
|
|
15527
|
+
slack_team_id: external_exports.string(),
|
|
15528
|
+
slack_team_name: external_exports.string().nullable(),
|
|
15529
|
+
slack_channel_id: external_exports.string(),
|
|
15530
|
+
slack_channel_name: external_exports.string().nullable(),
|
|
15531
|
+
installed_by_member_id: external_exports.string().nullable(),
|
|
15532
|
+
is_active: external_exports.boolean(),
|
|
15533
|
+
created_at: external_exports.string(),
|
|
15534
|
+
updated_at: external_exports.string()
|
|
15535
|
+
}).strict();
|
|
15536
|
+
var SlackDestinationListResponseSchema = external_exports.object({
|
|
15537
|
+
destinations: external_exports.array(SlackDestinationRecordSchema)
|
|
15538
|
+
}).strict();
|
|
15539
|
+
var SlackInstallUrlResponseSchema = external_exports.object({
|
|
15540
|
+
install_url: external_exports.string().url()
|
|
15541
|
+
}).strict();
|
|
15542
|
+
var SlackDestinationTestResponseSchema = external_exports.object({
|
|
15543
|
+
delivered: external_exports.boolean()
|
|
15544
|
+
}).strict();
|
|
15545
|
+
var ApiErrorResponseSchema6 = external_exports.object({
|
|
15546
|
+
error: external_exports.string()
|
|
15547
|
+
}).strict();
|
|
15548
|
+
var SlackApiError = class extends Error {
|
|
15549
|
+
status;
|
|
15550
|
+
code;
|
|
15551
|
+
constructor(status, code) {
|
|
15552
|
+
super(`slack_api_error: ${status}:${code}`);
|
|
15553
|
+
this.status = status;
|
|
15554
|
+
this.code = code;
|
|
15555
|
+
}
|
|
15556
|
+
};
|
|
15557
|
+
function parseApiError6(status, body) {
|
|
15558
|
+
const parsed = ApiErrorResponseSchema6.safeParse(body);
|
|
15559
|
+
if (!parsed.success) {
|
|
15560
|
+
throw new SlackApiError(status, "unknown_error");
|
|
15561
|
+
}
|
|
15562
|
+
throw new SlackApiError(status, parsed.data.error);
|
|
15563
|
+
}
|
|
15564
|
+
function buildQuery2(input) {
|
|
15565
|
+
const params = new URLSearchParams();
|
|
15566
|
+
for (const [key, value] of Object.entries(input)) {
|
|
15567
|
+
if (value !== void 0) {
|
|
15568
|
+
params.set(key, String(value));
|
|
15569
|
+
}
|
|
15570
|
+
}
|
|
15571
|
+
const query = params.toString();
|
|
15572
|
+
return query.length === 0 ? "" : `?${query}`;
|
|
15573
|
+
}
|
|
15574
|
+
function createSlackApi(client) {
|
|
15575
|
+
return {
|
|
15576
|
+
async getSlackInstallUrl(input) {
|
|
15577
|
+
const response = await client.request({
|
|
15578
|
+
method: "GET",
|
|
15579
|
+
path: `/v1/slack/app/install-url${buildQuery2({
|
|
15580
|
+
project_id: input.projectId,
|
|
15581
|
+
return_to: input.returnTo
|
|
15582
|
+
})}`,
|
|
15583
|
+
bearerToken: input.bearerToken
|
|
15584
|
+
});
|
|
15585
|
+
if (response.status < 200 || response.status >= 300) {
|
|
15586
|
+
parseApiError6(response.status, response.body);
|
|
15587
|
+
}
|
|
15588
|
+
const parsed = SlackInstallUrlResponseSchema.safeParse(response.body);
|
|
15589
|
+
if (!parsed.success) {
|
|
15590
|
+
throw new SlackApiError(response.status, "invalid_response_shape");
|
|
15591
|
+
}
|
|
15592
|
+
return parsed.data.install_url;
|
|
15593
|
+
},
|
|
15594
|
+
async listSlackDestinations(input) {
|
|
15595
|
+
const response = await client.request({
|
|
15596
|
+
method: "GET",
|
|
15597
|
+
path: `/v1/projects/${input.projectId}/slack/destinations`,
|
|
15598
|
+
bearerToken: input.bearerToken
|
|
15599
|
+
});
|
|
15600
|
+
if (response.status < 200 || response.status >= 300) {
|
|
15601
|
+
parseApiError6(response.status, response.body);
|
|
15602
|
+
}
|
|
15603
|
+
const parsed = SlackDestinationListResponseSchema.safeParse(response.body);
|
|
15604
|
+
if (!parsed.success) {
|
|
15605
|
+
throw new SlackApiError(response.status, "invalid_response_shape");
|
|
15606
|
+
}
|
|
15607
|
+
return parsed.data.destinations;
|
|
15608
|
+
},
|
|
15609
|
+
async testSlackDestination(input) {
|
|
15610
|
+
const response = await client.request({
|
|
15611
|
+
method: "POST",
|
|
15612
|
+
path: `/v1/projects/${input.projectId}/slack/destinations/${input.destinationId}/test`,
|
|
15613
|
+
bearerToken: input.bearerToken
|
|
15614
|
+
});
|
|
15615
|
+
if (response.status < 200 || response.status >= 300) {
|
|
15616
|
+
parseApiError6(response.status, response.body);
|
|
15617
|
+
}
|
|
15618
|
+
const parsed = SlackDestinationTestResponseSchema.safeParse(response.body);
|
|
15619
|
+
if (!parsed.success || parsed.data.delivered !== true) {
|
|
15620
|
+
throw new SlackApiError(response.status, "invalid_response_shape");
|
|
15621
|
+
}
|
|
15622
|
+
return { delivered: true };
|
|
15623
|
+
},
|
|
15624
|
+
async deleteSlackDestination(input) {
|
|
15625
|
+
const response = await client.request({
|
|
15626
|
+
method: "DELETE",
|
|
15627
|
+
path: `/v1/projects/${input.projectId}/slack/destinations/${input.destinationId}`,
|
|
15628
|
+
bearerToken: input.bearerToken
|
|
15629
|
+
});
|
|
15630
|
+
if (response.status < 200 || response.status >= 300) {
|
|
15631
|
+
parseApiError6(response.status, response.body);
|
|
15632
|
+
}
|
|
15633
|
+
return { slack_destination_id: input.destinationId };
|
|
15634
|
+
}
|
|
15635
|
+
};
|
|
15636
|
+
}
|
|
15637
|
+
|
|
15525
15638
|
// ../../packages/token-management/src/index.ts
|
|
15526
15639
|
var ProjectTokenSchema = external_exports.object({
|
|
15527
15640
|
token_id: external_exports.string(),
|
|
@@ -15550,7 +15663,7 @@ var TokenListResponseSchema = external_exports.object({
|
|
|
15550
15663
|
var TokenCreateResponseSchema = external_exports.object({
|
|
15551
15664
|
token: external_exports.union([ProjectTokenSchema, MemberTokenSchema])
|
|
15552
15665
|
}).strict();
|
|
15553
|
-
var
|
|
15666
|
+
var ApiErrorResponseSchema7 = external_exports.object({
|
|
15554
15667
|
error: external_exports.string()
|
|
15555
15668
|
}).strict();
|
|
15556
15669
|
var TokenManagementApiError = class extends Error {
|
|
@@ -15562,8 +15675,8 @@ var TokenManagementApiError = class extends Error {
|
|
|
15562
15675
|
this.code = code;
|
|
15563
15676
|
}
|
|
15564
15677
|
};
|
|
15565
|
-
function
|
|
15566
|
-
const parsed =
|
|
15678
|
+
function parseApiError7(status, body) {
|
|
15679
|
+
const parsed = ApiErrorResponseSchema7.safeParse(body);
|
|
15567
15680
|
if (!parsed.success) {
|
|
15568
15681
|
throw new TokenManagementApiError(status, "unknown_error");
|
|
15569
15682
|
}
|
|
@@ -15572,7 +15685,7 @@ function parseApiError6(status, body) {
|
|
|
15572
15685
|
async function expectTokenList(responsePromise) {
|
|
15573
15686
|
const response = await responsePromise;
|
|
15574
15687
|
if (response.status < 200 || response.status >= 300) {
|
|
15575
|
-
|
|
15688
|
+
parseApiError7(response.status, response.body);
|
|
15576
15689
|
}
|
|
15577
15690
|
const parsed = TokenListResponseSchema.safeParse(response.body);
|
|
15578
15691
|
if (!parsed.success) {
|
|
@@ -15583,7 +15696,7 @@ async function expectTokenList(responsePromise) {
|
|
|
15583
15696
|
async function expectToken(responsePromise) {
|
|
15584
15697
|
const response = await responsePromise;
|
|
15585
15698
|
if (response.status < 200 || response.status >= 300) {
|
|
15586
|
-
|
|
15699
|
+
parseApiError7(response.status, response.body);
|
|
15587
15700
|
}
|
|
15588
15701
|
const parsed = TokenCreateResponseSchema.safeParse(response.body);
|
|
15589
15702
|
if (!parsed.success) {
|
|
@@ -15775,7 +15888,7 @@ var RetryWebhookDeliveryResponseSchema = external_exports.object({
|
|
|
15775
15888
|
delivery_id: external_exports.string(),
|
|
15776
15889
|
event_type: WebhookEventTypeSchema
|
|
15777
15890
|
}).strict();
|
|
15778
|
-
var
|
|
15891
|
+
var ApiErrorResponseSchema8 = external_exports.object({
|
|
15779
15892
|
error: external_exports.string()
|
|
15780
15893
|
}).strict();
|
|
15781
15894
|
var WebhookApiError = class extends Error {
|
|
@@ -15787,14 +15900,14 @@ var WebhookApiError = class extends Error {
|
|
|
15787
15900
|
this.code = code;
|
|
15788
15901
|
}
|
|
15789
15902
|
};
|
|
15790
|
-
function
|
|
15791
|
-
const parsed =
|
|
15903
|
+
function parseApiError8(status, body) {
|
|
15904
|
+
const parsed = ApiErrorResponseSchema8.safeParse(body);
|
|
15792
15905
|
if (!parsed.success) {
|
|
15793
15906
|
throw new WebhookApiError(status, "unknown_error");
|
|
15794
15907
|
}
|
|
15795
15908
|
throw new WebhookApiError(status, parsed.data.error);
|
|
15796
15909
|
}
|
|
15797
|
-
function
|
|
15910
|
+
function buildQuery3(input) {
|
|
15798
15911
|
const params = new URLSearchParams();
|
|
15799
15912
|
for (const [key, value] of Object.entries(input)) {
|
|
15800
15913
|
if (value !== void 0) {
|
|
@@ -15807,7 +15920,7 @@ function buildQuery2(input) {
|
|
|
15807
15920
|
async function expectWebhookList(responsePromise) {
|
|
15808
15921
|
const response = await responsePromise;
|
|
15809
15922
|
if (response.status < 200 || response.status >= 300) {
|
|
15810
|
-
|
|
15923
|
+
parseApiError8(response.status, response.body);
|
|
15811
15924
|
}
|
|
15812
15925
|
const parsed = WebhookListResponseSchema.safeParse(response.body);
|
|
15813
15926
|
if (!parsed.success) {
|
|
@@ -15818,7 +15931,7 @@ async function expectWebhookList(responsePromise) {
|
|
|
15818
15931
|
async function expectWebhook(responsePromise) {
|
|
15819
15932
|
const response = await responsePromise;
|
|
15820
15933
|
if (response.status < 200 || response.status >= 300) {
|
|
15821
|
-
|
|
15934
|
+
parseApiError8(response.status, response.body);
|
|
15822
15935
|
}
|
|
15823
15936
|
const parsed = WebhookResponseSchema.safeParse(response.body);
|
|
15824
15937
|
if (!parsed.success) {
|
|
@@ -15829,7 +15942,7 @@ async function expectWebhook(responsePromise) {
|
|
|
15829
15942
|
async function expectCreatedWebhook(responsePromise) {
|
|
15830
15943
|
const response = await responsePromise;
|
|
15831
15944
|
if (response.status < 200 || response.status >= 300) {
|
|
15832
|
-
|
|
15945
|
+
parseApiError8(response.status, response.body);
|
|
15833
15946
|
}
|
|
15834
15947
|
const parsed = WebhookCreateResponseSchema.safeParse(response.body);
|
|
15835
15948
|
if (!parsed.success) {
|
|
@@ -15840,7 +15953,7 @@ async function expectCreatedWebhook(responsePromise) {
|
|
|
15840
15953
|
async function expectWebhookDeliveries(responsePromise) {
|
|
15841
15954
|
const response = await responsePromise;
|
|
15842
15955
|
if (response.status < 200 || response.status >= 300) {
|
|
15843
|
-
|
|
15956
|
+
parseApiError8(response.status, response.body);
|
|
15844
15957
|
}
|
|
15845
15958
|
const parsed = WebhookDeliveriesResponseSchema.safeParse(response.body);
|
|
15846
15959
|
if (!parsed.success) {
|
|
@@ -15851,7 +15964,7 @@ async function expectWebhookDeliveries(responsePromise) {
|
|
|
15851
15964
|
async function expectWebhookTestDelivery(responsePromise) {
|
|
15852
15965
|
const response = await responsePromise;
|
|
15853
15966
|
if (response.status < 200 || response.status >= 300) {
|
|
15854
|
-
|
|
15967
|
+
parseApiError8(response.status, response.body);
|
|
15855
15968
|
}
|
|
15856
15969
|
const parsed = WebhookTestResponseSchema.safeParse(response.body);
|
|
15857
15970
|
if (!parsed.success) {
|
|
@@ -15862,7 +15975,7 @@ async function expectWebhookTestDelivery(responsePromise) {
|
|
|
15862
15975
|
async function expectRetryDelivery(responsePromise) {
|
|
15863
15976
|
const response = await responsePromise;
|
|
15864
15977
|
if (response.status < 200 || response.status >= 300) {
|
|
15865
|
-
|
|
15978
|
+
parseApiError8(response.status, response.body);
|
|
15866
15979
|
}
|
|
15867
15980
|
const parsed = RetryWebhookDeliveryResponseSchema.safeParse(response.body);
|
|
15868
15981
|
if (!parsed.success) {
|
|
@@ -15876,7 +15989,7 @@ function createWebhookApi(client) {
|
|
|
15876
15989
|
return expectWebhookList(
|
|
15877
15990
|
client.request({
|
|
15878
15991
|
method: "GET",
|
|
15879
|
-
path: `/v1/webhooks${
|
|
15992
|
+
path: `/v1/webhooks${buildQuery3({ project_id: input.projectId, limit: input.limit })}`,
|
|
15880
15993
|
bearerToken: input.bearerToken
|
|
15881
15994
|
})
|
|
15882
15995
|
);
|
|
@@ -15941,7 +16054,7 @@ function createWebhookApi(client) {
|
|
|
15941
16054
|
bearerToken: input.bearerToken
|
|
15942
16055
|
});
|
|
15943
16056
|
if (response.status < 200 || response.status >= 300) {
|
|
15944
|
-
|
|
16057
|
+
parseApiError8(response.status, response.body);
|
|
15945
16058
|
}
|
|
15946
16059
|
return {
|
|
15947
16060
|
webhook_id: input.webhookId
|
|
@@ -15965,7 +16078,7 @@ function createWebhookApi(client) {
|
|
|
15965
16078
|
return expectWebhookDeliveries(
|
|
15966
16079
|
client.request({
|
|
15967
16080
|
method: "GET",
|
|
15968
|
-
path: `/v1/webhooks/${input.webhookId}/deliveries${
|
|
16081
|
+
path: `/v1/webhooks/${input.webhookId}/deliveries${buildQuery3({ limit: input.limit })}`,
|
|
15969
16082
|
bearerToken: input.bearerToken
|
|
15970
16083
|
})
|
|
15971
16084
|
);
|
|
@@ -16015,7 +16128,7 @@ var WeeklyReportChannelListResponseSchema = external_exports.object({
|
|
|
16015
16128
|
var WeeklyReportChannelResponseSchema = external_exports.object({
|
|
16016
16129
|
channel: WeeklyReportChannelRecordSchema
|
|
16017
16130
|
}).strict();
|
|
16018
|
-
var
|
|
16131
|
+
var ApiErrorResponseSchema9 = external_exports.object({
|
|
16019
16132
|
error: external_exports.string()
|
|
16020
16133
|
}).strict();
|
|
16021
16134
|
var WeeklyReportApiError = class extends Error {
|
|
@@ -16027,14 +16140,14 @@ var WeeklyReportApiError = class extends Error {
|
|
|
16027
16140
|
this.code = code;
|
|
16028
16141
|
}
|
|
16029
16142
|
};
|
|
16030
|
-
function
|
|
16031
|
-
const parsed =
|
|
16143
|
+
function parseApiError9(status, body) {
|
|
16144
|
+
const parsed = ApiErrorResponseSchema9.safeParse(body);
|
|
16032
16145
|
if (!parsed.success) {
|
|
16033
16146
|
throw new WeeklyReportApiError(status, "unknown_error");
|
|
16034
16147
|
}
|
|
16035
16148
|
throw new WeeklyReportApiError(status, parsed.data.error);
|
|
16036
16149
|
}
|
|
16037
|
-
function
|
|
16150
|
+
function buildQuery4(input) {
|
|
16038
16151
|
const params = new URLSearchParams();
|
|
16039
16152
|
for (const [key, value] of Object.entries(input)) {
|
|
16040
16153
|
if (value !== void 0) {
|
|
@@ -16047,7 +16160,7 @@ function buildQuery3(input) {
|
|
|
16047
16160
|
async function expectChannelList(responsePromise) {
|
|
16048
16161
|
const response = await responsePromise;
|
|
16049
16162
|
if (response.status < 200 || response.status >= 300) {
|
|
16050
|
-
|
|
16163
|
+
parseApiError9(response.status, response.body);
|
|
16051
16164
|
}
|
|
16052
16165
|
const parsed = WeeklyReportChannelListResponseSchema.safeParse(response.body);
|
|
16053
16166
|
if (!parsed.success) {
|
|
@@ -16058,7 +16171,7 @@ async function expectChannelList(responsePromise) {
|
|
|
16058
16171
|
async function expectChannel(responsePromise) {
|
|
16059
16172
|
const response = await responsePromise;
|
|
16060
16173
|
if (response.status < 200 || response.status >= 300) {
|
|
16061
|
-
|
|
16174
|
+
parseApiError9(response.status, response.body);
|
|
16062
16175
|
}
|
|
16063
16176
|
const parsed = WeeklyReportChannelResponseSchema.safeParse(response.body);
|
|
16064
16177
|
if (!parsed.success) {
|
|
@@ -16072,13 +16185,13 @@ function createWeeklyReportApi(client) {
|
|
|
16072
16185
|
return expectChannelList(
|
|
16073
16186
|
client.request({
|
|
16074
16187
|
method: "GET",
|
|
16075
|
-
path: `/v1/weekly-report-channels${
|
|
16188
|
+
path: `/v1/weekly-report-channels${buildQuery4({ project_id: input.projectId, limit: input.limit })}`,
|
|
16076
16189
|
bearerToken: input.bearerToken
|
|
16077
16190
|
})
|
|
16078
16191
|
);
|
|
16079
16192
|
},
|
|
16080
16193
|
async createWeeklyReportChannel(input) {
|
|
16081
|
-
const config = input.channel === "email" ? { to: input.config.to } : { webhook_url: input.config.webhookUrl };
|
|
16194
|
+
const config = input.channel === "email" ? { to: input.config.to } : "webhookUrl" in input.config ? { webhook_url: input.config.webhookUrl } : { slack_destination_id: input.config.slackDestinationId };
|
|
16082
16195
|
return expectChannel(
|
|
16083
16196
|
client.request({
|
|
16084
16197
|
method: "POST",
|
|
@@ -16101,7 +16214,7 @@ function createWeeklyReportApi(client) {
|
|
|
16101
16214
|
async updateWeeklyReportChannel(input) {
|
|
16102
16215
|
const body = {};
|
|
16103
16216
|
if (input.config !== void 0) {
|
|
16104
|
-
body["config"] = "to" in input.config ? { to: input.config.to } : { webhook_url: input.config.webhookUrl };
|
|
16217
|
+
body["config"] = "to" in input.config ? { to: input.config.to } : "webhookUrl" in input.config ? { webhook_url: input.config.webhookUrl } : { slack_destination_id: input.config.slackDestinationId };
|
|
16105
16218
|
}
|
|
16106
16219
|
if (input.schedule !== void 0) {
|
|
16107
16220
|
body["schedule"] = {
|
|
@@ -16129,7 +16242,7 @@ function createWeeklyReportApi(client) {
|
|
|
16129
16242
|
bearerToken: input.bearerToken
|
|
16130
16243
|
});
|
|
16131
16244
|
if (response.status < 200 || response.status >= 300) {
|
|
16132
|
-
|
|
16245
|
+
parseApiError9(response.status, response.body);
|
|
16133
16246
|
}
|
|
16134
16247
|
return { channel_id: input.channelId };
|
|
16135
16248
|
}
|
|
@@ -16161,6 +16274,8 @@ var CaptureBreadcrumbsValues = ["local_only", "exception_only", "standalone"];
|
|
|
16161
16274
|
var CaptureBreadcrumbsSchema = external_exports.enum(CaptureBreadcrumbsValues);
|
|
16162
16275
|
var CaptureProbeEventsValues = ["buffer_only", "standalone_when_activated"];
|
|
16163
16276
|
var CaptureProbeEventsSchema = external_exports.enum(CaptureProbeEventsValues);
|
|
16277
|
+
var RequestSignalClassificationValues = ["incident_signal", "context_signal"];
|
|
16278
|
+
var RequestSignalClassificationSchema = external_exports.enum(RequestSignalClassificationValues);
|
|
16164
16279
|
var CapturePolicySchema = external_exports.object({
|
|
16165
16280
|
project_id: external_exports.string().uuid(),
|
|
16166
16281
|
preset: CapturePresetSchema,
|
|
@@ -16177,6 +16292,55 @@ var CapturePolicyUpdateSchema = external_exports.object({
|
|
|
16177
16292
|
capture_breadcrumbs: CaptureBreadcrumbsSchema.nullable().optional(),
|
|
16178
16293
|
capture_probe_events: CaptureProbeEventsSchema.nullable().optional()
|
|
16179
16294
|
});
|
|
16295
|
+
var BALANCED_IMMEDIATE_REQUEST_STATUSES = /* @__PURE__ */ new Set([408, 423, 424, 425, 429]);
|
|
16296
|
+
var INVESTIGATIVE_IMMEDIATE_REQUEST_STATUSES = /* @__PURE__ */ new Set([...BALANCED_IMMEDIATE_REQUEST_STATUSES, 409]);
|
|
16297
|
+
var BALANCED_STANDARD_ANOMALY_STATUSES = /* @__PURE__ */ new Set([401, 403, 404, 409, 422]);
|
|
16298
|
+
var BALANCED_HIGH_VOLUME_ANOMALY_STATUSES = /* @__PURE__ */ new Set([400, 410]);
|
|
16299
|
+
var INVESTIGATIVE_ANOMALY_STATUSES = /* @__PURE__ */ new Set([...BALANCED_STANDARD_ANOMALY_STATUSES, ...BALANCED_HIGH_VOLUME_ANOMALY_STATUSES]);
|
|
16300
|
+
function classifyRequestStatus(input) {
|
|
16301
|
+
const { responseStatus, capturePreset } = input;
|
|
16302
|
+
if (responseStatus === null || !Number.isFinite(responseStatus)) {
|
|
16303
|
+
return "context_signal";
|
|
16304
|
+
}
|
|
16305
|
+
if (responseStatus >= 500) {
|
|
16306
|
+
return "incident_signal";
|
|
16307
|
+
}
|
|
16308
|
+
if (capturePreset === "investigative") {
|
|
16309
|
+
return INVESTIGATIVE_IMMEDIATE_REQUEST_STATUSES.has(responseStatus) ? "incident_signal" : "context_signal";
|
|
16310
|
+
}
|
|
16311
|
+
if (capturePreset === "balanced") {
|
|
16312
|
+
return BALANCED_IMMEDIATE_REQUEST_STATUSES.has(responseStatus) ? "incident_signal" : "context_signal";
|
|
16313
|
+
}
|
|
16314
|
+
return "context_signal";
|
|
16315
|
+
}
|
|
16316
|
+
function getRequestAnomalyThreshold(input) {
|
|
16317
|
+
const { responseStatus, capturePreset } = input;
|
|
16318
|
+
if (responseStatus === null || !Number.isFinite(responseStatus) || responseStatus < 400 || responseStatus >= 500) {
|
|
16319
|
+
return null;
|
|
16320
|
+
}
|
|
16321
|
+
if (capturePreset === "minimal") {
|
|
16322
|
+
return null;
|
|
16323
|
+
}
|
|
16324
|
+
if (capturePreset === "investigative") {
|
|
16325
|
+
return INVESTIGATIVE_ANOMALY_STATUSES.has(responseStatus) ? {
|
|
16326
|
+
minimum_occurrences_5m: 8,
|
|
16327
|
+
minimum_ratio_5m_to_1h: 2
|
|
16328
|
+
} : null;
|
|
16329
|
+
}
|
|
16330
|
+
if (BALANCED_STANDARD_ANOMALY_STATUSES.has(responseStatus)) {
|
|
16331
|
+
return {
|
|
16332
|
+
minimum_occurrences_5m: 20,
|
|
16333
|
+
minimum_ratio_5m_to_1h: 3
|
|
16334
|
+
};
|
|
16335
|
+
}
|
|
16336
|
+
if (BALANCED_HIGH_VOLUME_ANOMALY_STATUSES.has(responseStatus)) {
|
|
16337
|
+
return {
|
|
16338
|
+
minimum_occurrences_5m: 50,
|
|
16339
|
+
minimum_ratio_5m_to_1h: 5
|
|
16340
|
+
};
|
|
16341
|
+
}
|
|
16342
|
+
return null;
|
|
16343
|
+
}
|
|
16180
16344
|
|
|
16181
16345
|
// ../../packages/shared-types/src/index.ts
|
|
16182
16346
|
function createUuidV4() {
|
|
@@ -16225,6 +16389,26 @@ var InlineProbeDataSchema = external_exports.object({
|
|
|
16225
16389
|
version: external_exports.literal(1),
|
|
16226
16390
|
items: external_exports.array(InlineProbeDataItemSchema)
|
|
16227
16391
|
}).strict();
|
|
16392
|
+
var RuntimeMemoryStatsSchema = external_exports.object({
|
|
16393
|
+
rss: external_exports.number().nonnegative().nullable(),
|
|
16394
|
+
heap_total: external_exports.number().nonnegative().nullable(),
|
|
16395
|
+
heap_used: external_exports.number().nonnegative().nullable(),
|
|
16396
|
+
external: external_exports.number().nonnegative().nullable(),
|
|
16397
|
+
peak: external_exports.number().nonnegative().nullable()
|
|
16398
|
+
}).strict();
|
|
16399
|
+
var BackendRuntimePayloadSchema = external_exports.object({
|
|
16400
|
+
version: external_exports.string().min(1),
|
|
16401
|
+
platform: external_exports.string().min(1).nullable().optional(),
|
|
16402
|
+
arch: external_exports.string().min(1).nullable().optional(),
|
|
16403
|
+
pid: external_exports.number().int().nonnegative().nullable().optional(),
|
|
16404
|
+
cwd: external_exports.string().min(1).nullable().optional(),
|
|
16405
|
+
uptime_sec: external_exports.number().nonnegative().nullable().optional(),
|
|
16406
|
+
hostname: external_exports.string().min(1).nullable().optional(),
|
|
16407
|
+
thread_id: external_exports.union([external_exports.string(), external_exports.number()]).nullable().optional(),
|
|
16408
|
+
framework_version: external_exports.string().min(1).nullable().optional(),
|
|
16409
|
+
memory: RuntimeMemoryStatsSchema.nullable().optional(),
|
|
16410
|
+
framework_extras: external_exports.record(external_exports.string(), external_exports.unknown()).nullable().optional()
|
|
16411
|
+
}).strict();
|
|
16228
16412
|
var BackendExceptionPayloadSchema = external_exports.object({
|
|
16229
16413
|
name: external_exports.string().min(1),
|
|
16230
16414
|
message: external_exports.string().min(1),
|
|
@@ -16242,9 +16426,7 @@ var BackendExceptionPayloadSchema = external_exports.object({
|
|
|
16242
16426
|
headers: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
|
|
16243
16427
|
body: external_exports.unknown().optional()
|
|
16244
16428
|
}),
|
|
16245
|
-
runtime:
|
|
16246
|
-
version: external_exports.string().min(1)
|
|
16247
|
-
}),
|
|
16429
|
+
runtime: BackendRuntimePayloadSchema,
|
|
16248
16430
|
probe_data: InlineProbeDataSchema.optional()
|
|
16249
16431
|
}).strict();
|
|
16250
16432
|
var RequestEventPayloadSchema = external_exports.object({
|
|
@@ -16515,13 +16697,7 @@ var ContextDeploySchema = external_exports.object({
|
|
|
16515
16697
|
deployed_at: external_exports.string().datetime().nullable(),
|
|
16516
16698
|
regression_window: external_exports.boolean().nullable()
|
|
16517
16699
|
});
|
|
16518
|
-
var MemoryStatsSchema =
|
|
16519
|
-
rss: external_exports.number().nonnegative().nullable(),
|
|
16520
|
-
heap_total: external_exports.number().nonnegative().nullable(),
|
|
16521
|
-
heap_used: external_exports.number().nonnegative().nullable(),
|
|
16522
|
-
external: external_exports.number().nonnegative().nullable(),
|
|
16523
|
-
peak: external_exports.number().nonnegative().nullable()
|
|
16524
|
-
});
|
|
16700
|
+
var MemoryStatsSchema = RuntimeMemoryStatsSchema;
|
|
16525
16701
|
var ContextRuntimeSchema = external_exports.object({
|
|
16526
16702
|
version: external_exports.literal(1),
|
|
16527
16703
|
name: external_exports.string().min(1),
|
|
@@ -16773,7 +16949,7 @@ function buildCliReference() {
|
|
|
16773
16949
|
"- `debugbundle ingest <file> --format <format> [--json]`",
|
|
16774
16950
|
"- `debugbundle watch --log <file> --format <format> [--json]`",
|
|
16775
16951
|
"- `debugbundle watch --cloud --log <file> --format <format> [--json]`",
|
|
16776
|
-
"- `debugbundle process [--json]`",
|
|
16952
|
+
"- `debugbundle process [--preset <minimal|balanced|investigative>] [--json]`",
|
|
16777
16953
|
"",
|
|
16778
16954
|
"## Investigation",
|
|
16779
16955
|
"",
|
|
@@ -17865,7 +18041,7 @@ function getRequestResponseStatus(payload) {
|
|
|
17865
18041
|
const status = payload?.["response_status"];
|
|
17866
18042
|
return typeof status === "number" && Number.isFinite(status) ? status : null;
|
|
17867
18043
|
}
|
|
17868
|
-
function classifyEvent(eventType, logLevel, probeActivationId, payload) {
|
|
18044
|
+
function classifyEvent(eventType, logLevel, probeActivationId, payload, capturePreset = "minimal") {
|
|
17869
18045
|
switch (eventType) {
|
|
17870
18046
|
case "backend_exception":
|
|
17871
18047
|
case "frontend_exception":
|
|
@@ -17877,10 +18053,7 @@ function classifyEvent(eventType, logLevel, probeActivationId, payload) {
|
|
|
17877
18053
|
return "context_signal";
|
|
17878
18054
|
case "request_event": {
|
|
17879
18055
|
const responseStatus = getRequestResponseStatus(payload);
|
|
17880
|
-
|
|
17881
|
-
return "incident_signal";
|
|
17882
|
-
}
|
|
17883
|
-
return "context_signal";
|
|
18056
|
+
return classifyRequestStatus({ responseStatus, capturePreset });
|
|
17884
18057
|
}
|
|
17885
18058
|
case "frontend_breadcrumb":
|
|
17886
18059
|
case "deploy_metadata":
|
|
@@ -17929,7 +18102,7 @@ var RELAY_SPOOL_DELIVERED_MARKER_SUFFIX = ".delivered";
|
|
|
17929
18102
|
var RELAY_SPOOL_EVENT_SUFFIX = ".events.json";
|
|
17930
18103
|
var SUGGESTED_ACTIONS = [
|
|
17931
18104
|
"Run debugbundle setup if local scaffold files are missing.",
|
|
17932
|
-
"Run debugbundle login to create ~/.debugbundle/auth.json.",
|
|
18105
|
+
"Run debugbundle login to choose an auth flow, or use debugbundle login --github, debugbundle login --github-device, or debugbundle login <dbundle_mem_...> to create ~/.debugbundle/auth.json.",
|
|
17933
18106
|
"Review .debugbundle/profile.json when architecture changes or the profile becomes stale."
|
|
17934
18107
|
];
|
|
17935
18108
|
async function pathExists3(path, stat) {
|
|
@@ -18042,7 +18215,7 @@ function buildPrivacyPreview() {
|
|
|
18042
18215
|
sample_event_type: sampleEvent.event_type,
|
|
18043
18216
|
sample_event_class: sampleEventClass,
|
|
18044
18217
|
sample_can_create_incident: sampleEventClass === "incident_signal",
|
|
18045
|
-
incident_rule: "request_event
|
|
18218
|
+
incident_rule: "request_event incident classification follows the resolved capture preset: 5xx always create incidents, balanced also promotes 408/423/424/425/429, and investigative also promotes 409.",
|
|
18046
18219
|
redacted_fields,
|
|
18047
18220
|
omitted_fields: [],
|
|
18048
18221
|
retained_metadata: {
|
|
@@ -18553,7 +18726,8 @@ function buildRedactionRecord(bundleBody) {
|
|
|
18553
18726
|
function buildVisibilityRecord(input) {
|
|
18554
18727
|
const routeTarget = input.primarySignal.route_template ?? input.primarySignal.request_path;
|
|
18555
18728
|
const matchedFields = input.incident.matched_fields.length === 0 ? "none" : input.incident.matched_fields.join(", ");
|
|
18556
|
-
const
|
|
18729
|
+
const isRequestAnomaly = input.incident.matched_fields.includes("request_anomaly");
|
|
18730
|
+
const grouping = input.primarySignal.kind === "request_failure" && input.primarySignal.request_method !== null && routeTarget !== null ? isRequestAnomaly ? `Repeated request-anomaly incidents with the same normalized route template, request method, response status, service, and environment reuse this incident fingerprint once the anomaly threshold fires. This incident currently groups ${input.primarySignal.request_method} ${routeTarget} with matched fields ${matchedFields}.` : `Repeated request-failure incidents with the same normalized route template, request method, response status, service, and environment reuse this incident fingerprint. This incident currently groups ${input.primarySignal.request_method} ${routeTarget} with matched fields ${matchedFields}.` : `This incident groups repeated failures by fingerprint version ${input.incident.fingerprint_version} inside the service and environment boundary, with matched fields ${matchedFields}.`;
|
|
18557
18731
|
const spikeLead = input.incident.spike_detected_at === void 0 || input.incident.spike_detected_at === null ? "This incident is not currently marked as spiking." : `This incident was marked as spiking at ${input.incident.spike_detected_at}.`;
|
|
18558
18732
|
return {
|
|
18559
18733
|
grouping,
|
|
@@ -18564,15 +18738,16 @@ function buildVisibilityRecord(input) {
|
|
|
18564
18738
|
}
|
|
18565
18739
|
function buildSuggestedNextChecks(input) {
|
|
18566
18740
|
const suggestions = [];
|
|
18741
|
+
const isRequestAnomaly = input.incident.matched_fields.includes("request_anomaly");
|
|
18567
18742
|
if (input.bundle.status === "pending") {
|
|
18568
18743
|
suggestions.push("Wait for bundle generation to finish, then rerun the incident context command.");
|
|
18569
18744
|
} else if (input.bundle.status === "failed") {
|
|
18570
18745
|
suggestions.push("Inspect bundle generation status or retry bundle retrieval to recover missing context.");
|
|
18571
18746
|
}
|
|
18572
18747
|
const routeTarget = input.primarySignal.route_template ?? input.primarySignal.request_path;
|
|
18573
|
-
if (input.primarySignal.
|
|
18748
|
+
if (input.primarySignal.kind === "request_failure" && input.primarySignal.request_method !== null && routeTarget !== null) {
|
|
18574
18749
|
suggestions.push(
|
|
18575
|
-
`Inspect the ${input.primarySignal.request_method} ${routeTarget
|
|
18750
|
+
isRequestAnomaly ? `Inspect the ${input.primarySignal.request_method} ${routeTarget} handler behind this repeated request-anomaly path.` : `Inspect the ${input.primarySignal.request_method} ${routeTarget} handler behind this request-failure path.`
|
|
18576
18751
|
);
|
|
18577
18752
|
}
|
|
18578
18753
|
const firstApplicationFrame = input.primarySignal.first_application_frame;
|
|
@@ -18661,12 +18836,13 @@ function deriveIncidentReasonFromSignal(input) {
|
|
|
18661
18836
|
};
|
|
18662
18837
|
case "request_event": {
|
|
18663
18838
|
const responseStatus = typeof input.response_status === "number" && Number.isFinite(input.response_status) ? input.response_status : null;
|
|
18839
|
+
const isRequestAnomaly = input.request_anomaly === true;
|
|
18664
18840
|
return {
|
|
18665
|
-
kind: "
|
|
18666
|
-
description: responseStatus !== null
|
|
18841
|
+
kind: "request_failure",
|
|
18842
|
+
description: isRequestAnomaly ? responseStatus !== null ? `request_event response_status=${responseStatus} crossed the repeated request anomaly threshold` : "request_event crossed the repeated request anomaly threshold" : responseStatus !== null ? `request_event response_status=${responseStatus} matched the immediate request failure incident rule` : "request_event matched the immediate request failure incident rule",
|
|
18667
18843
|
event_type: "request_event",
|
|
18668
18844
|
event_class: "incident_signal",
|
|
18669
|
-
matched_policy: "
|
|
18845
|
+
matched_policy: isRequestAnomaly ? "Repeated contextual request failures crossed the request anomaly threshold" : "Immediate request failure statuses bypass capture_request_events suppression"
|
|
18670
18846
|
};
|
|
18671
18847
|
}
|
|
18672
18848
|
case "log_event": {
|
|
@@ -18695,9 +18871,11 @@ function deriveIncidentReasonFromSourceEventTypes(eventTypes) {
|
|
|
18695
18871
|
return null;
|
|
18696
18872
|
}
|
|
18697
18873
|
|
|
18698
|
-
// ../../packages/auth/src/
|
|
18874
|
+
// ../../packages/auth/src/primitives.ts
|
|
18699
18875
|
var import_argon2 = require("@node-rs/argon2");
|
|
18700
|
-
|
|
18876
|
+
|
|
18877
|
+
// ../../packages/auth/src/web-session-auth.ts
|
|
18878
|
+
var DEFAULT_SESSION_LIFETIME_MS = 1e3 * 60 * 60 * 24 * 7;
|
|
18701
18879
|
var DEFAULT_EMAIL_AUTH_CODE_LIFETIME_MS = 1e3 * 60 * 10;
|
|
18702
18880
|
var DEFAULT_GITHUB_OAUTH_STATE_LIFETIME_MS = 1e3 * 60 * 10;
|
|
18703
18881
|
|
|
@@ -18736,6 +18914,70 @@ var STORAGE_SCHEMA_MIGRATIONS = [
|
|
|
18736
18914
|
"ALTER TABLE organizations ADD COLUMN IF NOT EXISTS suspended_at timestamptz",
|
|
18737
18915
|
"ALTER TABLE organization_members ADD COLUMN IF NOT EXISTS suspended_at timestamptz"
|
|
18738
18916
|
]
|
|
18917
|
+
}),
|
|
18918
|
+
defineStorageSchemaMigration({
|
|
18919
|
+
id: "202605120001_add_github_device_authorizations",
|
|
18920
|
+
description: "Add persisted GitHub CLI bootstrap state for device-flow login.",
|
|
18921
|
+
statements: [
|
|
18922
|
+
`
|
|
18923
|
+
CREATE TABLE IF NOT EXISTS github_device_authorizations (
|
|
18924
|
+
id uuid PRIMARY KEY,
|
|
18925
|
+
device_code text NOT NULL UNIQUE,
|
|
18926
|
+
user_code text NOT NULL,
|
|
18927
|
+
verification_uri text NOT NULL,
|
|
18928
|
+
interval_seconds integer NOT NULL,
|
|
18929
|
+
expires_at timestamptz NOT NULL,
|
|
18930
|
+
accepted_terms_at timestamptz,
|
|
18931
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
18932
|
+
completed_at timestamptz,
|
|
18933
|
+
claimed_at timestamptz,
|
|
18934
|
+
terminal_error text,
|
|
18935
|
+
user_id uuid REFERENCES users(id) ON DELETE SET NULL,
|
|
18936
|
+
organization_id uuid REFERENCES organizations(id) ON DELETE SET NULL
|
|
18937
|
+
)
|
|
18938
|
+
`,
|
|
18939
|
+
`
|
|
18940
|
+
CREATE INDEX IF NOT EXISTS github_device_authorizations_user_code_idx
|
|
18941
|
+
ON github_device_authorizations (user_code, created_at DESC)
|
|
18942
|
+
`,
|
|
18943
|
+
`
|
|
18944
|
+
CREATE INDEX IF NOT EXISTS github_device_authorizations_expires_at_idx
|
|
18945
|
+
ON github_device_authorizations (expires_at)
|
|
18946
|
+
`
|
|
18947
|
+
]
|
|
18948
|
+
}),
|
|
18949
|
+
defineStorageSchemaMigration({
|
|
18950
|
+
id: "202605130001_allow_synthetic_webhook_test_deliveries_without_incident_fk",
|
|
18951
|
+
description: "Allow webhook test deliveries to persist without requiring a backing incidents row.",
|
|
18952
|
+
statements: [
|
|
18953
|
+
"ALTER TABLE webhook_deliveries ALTER COLUMN incident_id DROP NOT NULL"
|
|
18954
|
+
]
|
|
18955
|
+
}),
|
|
18956
|
+
defineStorageSchemaMigration({
|
|
18957
|
+
id: "202605130002_add_slack_destinations",
|
|
18958
|
+
description: "Add reusable encrypted Slack alert destinations scoped to organizations.",
|
|
18959
|
+
statements: [
|
|
18960
|
+
`
|
|
18961
|
+
CREATE TABLE IF NOT EXISTS slack_destinations (
|
|
18962
|
+
id uuid PRIMARY KEY,
|
|
18963
|
+
organization_id uuid NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
|
18964
|
+
slack_team_id text NOT NULL,
|
|
18965
|
+
slack_team_name text,
|
|
18966
|
+
slack_channel_id text NOT NULL,
|
|
18967
|
+
slack_channel_name text,
|
|
18968
|
+
webhook_url_ciphertext text NOT NULL,
|
|
18969
|
+
installed_by_member_id uuid REFERENCES users(id) ON DELETE SET NULL,
|
|
18970
|
+
is_active boolean NOT NULL DEFAULT true,
|
|
18971
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
18972
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
18973
|
+
UNIQUE (organization_id, slack_team_id, slack_channel_id)
|
|
18974
|
+
)
|
|
18975
|
+
`,
|
|
18976
|
+
`
|
|
18977
|
+
CREATE INDEX IF NOT EXISTS slack_destinations_org_active_idx
|
|
18978
|
+
ON slack_destinations (organization_id, is_active, created_at)
|
|
18979
|
+
`
|
|
18980
|
+
]
|
|
18739
18981
|
})
|
|
18740
18982
|
];
|
|
18741
18983
|
|
|
@@ -18749,6 +18991,7 @@ var import_promises5 = require("node:fs/promises");
|
|
|
18749
18991
|
var import_node_path6 = require("node:path");
|
|
18750
18992
|
|
|
18751
18993
|
// ../../packages/bundle-engine/src/index.ts
|
|
18994
|
+
var DYNAMIC_SEGMENT_PATTERN2 = /^(?:\d+|[0-9a-f]{8}-[0-9a-f-]{27}|[A-Za-z0-9_-]{24,})$/;
|
|
18752
18995
|
function toIsoTimestamp(value) {
|
|
18753
18996
|
return new Date(value).toISOString();
|
|
18754
18997
|
}
|
|
@@ -18822,6 +19065,41 @@ function inferSignalTypeFromSourceEventTypes(sourceEventTypes) {
|
|
|
18822
19065
|
function extractTopFrames(stack) {
|
|
18823
19066
|
return stack.split("\n").map((line) => line.trim()).filter((line) => line.startsWith("at ")).slice(0, 3);
|
|
18824
19067
|
}
|
|
19068
|
+
function decodeRouteSegment2(segment) {
|
|
19069
|
+
try {
|
|
19070
|
+
return decodeURIComponent(segment);
|
|
19071
|
+
} catch {
|
|
19072
|
+
return segment.replace(
|
|
19073
|
+
/%([0-9A-Fa-f]{2})/g,
|
|
19074
|
+
(_match, hexByte) => String.fromCharCode(parseInt(hexByte, 16))
|
|
19075
|
+
);
|
|
19076
|
+
}
|
|
19077
|
+
}
|
|
19078
|
+
function isDynamicRouteSegment2(segment) {
|
|
19079
|
+
if (DYNAMIC_SEGMENT_PATTERN2.test(segment)) {
|
|
19080
|
+
return true;
|
|
19081
|
+
}
|
|
19082
|
+
const decodedSegment = decodeRouteSegment2(segment);
|
|
19083
|
+
if (decodedSegment.includes("/")) {
|
|
19084
|
+
return true;
|
|
19085
|
+
}
|
|
19086
|
+
if (decodedSegment !== segment && DYNAMIC_SEGMENT_PATTERN2.test(decodedSegment)) {
|
|
19087
|
+
return true;
|
|
19088
|
+
}
|
|
19089
|
+
const strippedMalformedPercent = decodedSegment.replace(/%+/g, "");
|
|
19090
|
+
return strippedMalformedPercent !== decodedSegment && DYNAMIC_SEGMENT_PATTERN2.test(strippedMalformedPercent);
|
|
19091
|
+
}
|
|
19092
|
+
function normalizeRouteTemplate(path) {
|
|
19093
|
+
if (path === null || path.length === 0) {
|
|
19094
|
+
return null;
|
|
19095
|
+
}
|
|
19096
|
+
const pathWithoutQueryOrFragment = path.split(/[?#]/, 1)[0] ?? "";
|
|
19097
|
+
if (pathWithoutQueryOrFragment.length === 0) {
|
|
19098
|
+
return "/";
|
|
19099
|
+
}
|
|
19100
|
+
const normalizedSegments = pathWithoutQueryOrFragment.split("/").filter((segment) => segment.length > 0).map((segment) => isDynamicRouteSegment2(segment) ? "{param}" : segment);
|
|
19101
|
+
return normalizedSegments.length === 0 ? "/" : `/${normalizedSegments.join("/")}`;
|
|
19102
|
+
}
|
|
18825
19103
|
function deriveFirstApplicationFrame(errorContext) {
|
|
18826
19104
|
const firstFrame = errorContext?.top_frames[0];
|
|
18827
19105
|
if (firstFrame === void 0) {
|
|
@@ -18915,13 +19193,135 @@ function buildRequestContext(envelopes) {
|
|
|
18915
19193
|
version: 1,
|
|
18916
19194
|
method: exceptionEvent.payload.request.method,
|
|
18917
19195
|
path: exceptionEvent.payload.request.path,
|
|
18918
|
-
route_template:
|
|
19196
|
+
route_template: normalizeRouteTemplate(exceptionEvent.payload.request.path),
|
|
18919
19197
|
query: exceptionEvent.payload.request.query,
|
|
18920
19198
|
headers: exceptionEvent.payload.request.headers,
|
|
18921
19199
|
body: exceptionEvent.payload.request.body ?? null,
|
|
18922
19200
|
request_id: exceptionEvent.correlation?.request_id ?? null
|
|
18923
19201
|
};
|
|
18924
19202
|
}
|
|
19203
|
+
function titleCaseWord(value) {
|
|
19204
|
+
if (value.toLowerCase() === "github") {
|
|
19205
|
+
return "GitHub";
|
|
19206
|
+
}
|
|
19207
|
+
if (value.toLowerCase() === "api") {
|
|
19208
|
+
return "API";
|
|
19209
|
+
}
|
|
19210
|
+
return `${value.slice(0, 1).toUpperCase()}${value.slice(1)}`;
|
|
19211
|
+
}
|
|
19212
|
+
function formatDependencyName(name) {
|
|
19213
|
+
return name.split("_").filter((part) => part.length > 0).map(titleCaseWord).join(" ");
|
|
19214
|
+
}
|
|
19215
|
+
function inferDependencyName(text) {
|
|
19216
|
+
const match = /\b([a-z][a-z0-9]*_api)_(?:invalid_response|error|failure|failed|unavailable|timeout)\b/.exec(text);
|
|
19217
|
+
return match?.[1] ?? null;
|
|
19218
|
+
}
|
|
19219
|
+
function buildDependenciesContext(incident, errorContext, requestContext) {
|
|
19220
|
+
if (errorContext === null) {
|
|
19221
|
+
return null;
|
|
19222
|
+
}
|
|
19223
|
+
const text = `${incident.title} ${errorContext.name} ${errorContext.message}`.toLowerCase();
|
|
19224
|
+
const dependencyName = inferDependencyName(text);
|
|
19225
|
+
if (dependencyName === null) {
|
|
19226
|
+
return null;
|
|
19227
|
+
}
|
|
19228
|
+
const displayName = formatDependencyName(dependencyName);
|
|
19229
|
+
const route = requestContext?.route_template ?? requestContext?.path ?? null;
|
|
19230
|
+
const requestDescription = requestContext !== null ? `${requestContext.method} ${route ?? requestContext.path}` : "the failing request";
|
|
19231
|
+
const invalidResponse = text.includes("invalid_response");
|
|
19232
|
+
return {
|
|
19233
|
+
version: 1,
|
|
19234
|
+
items: [
|
|
19235
|
+
{
|
|
19236
|
+
name: dependencyName,
|
|
19237
|
+
status: "failed",
|
|
19238
|
+
notes: invalidResponse ? `${displayName} returned an unexpected response shape while handling ${requestDescription}.` : `${displayName} failed while handling ${requestDescription}.`
|
|
19239
|
+
}
|
|
19240
|
+
]
|
|
19241
|
+
};
|
|
19242
|
+
}
|
|
19243
|
+
function buildSummaryGuidance(input) {
|
|
19244
|
+
if (input.errorContext === null) {
|
|
19245
|
+
return {
|
|
19246
|
+
likely_cause: null,
|
|
19247
|
+
confidence: 0,
|
|
19248
|
+
recommended_action: null
|
|
19249
|
+
};
|
|
19250
|
+
}
|
|
19251
|
+
const route = input.requestContext?.route_template ?? input.requestContext?.path ?? null;
|
|
19252
|
+
const requestDescription = input.requestContext !== null ? `${input.requestContext.method} ${route ?? input.requestContext.path}` : null;
|
|
19253
|
+
const firstDependency = input.dependenciesContext?.items[0] ?? null;
|
|
19254
|
+
const dependencyDisplayName = firstDependency !== null ? formatDependencyName(firstDependency.name) : null;
|
|
19255
|
+
const firstFrame = input.firstApplicationFrame;
|
|
19256
|
+
const frameDescription = firstFrame?.file !== null && firstFrame?.file !== void 0 ? ` in ${firstFrame.file}` : "";
|
|
19257
|
+
const invalidResponse = input.errorContext.message.toLowerCase().includes("invalid_response");
|
|
19258
|
+
let likelyCause = null;
|
|
19259
|
+
let recommendedAction = null;
|
|
19260
|
+
if (firstDependency !== null && dependencyDisplayName !== null && requestDescription !== null && invalidResponse) {
|
|
19261
|
+
likelyCause = `${dependencyDisplayName} returned a response that did not match the expected schema while handling ${requestDescription}.`;
|
|
19262
|
+
recommendedAction = `Inspect the ${dependencyDisplayName} response handling${frameDescription}, including schema validation and sanitized upstream response shape.`;
|
|
19263
|
+
} else if (firstDependency !== null && dependencyDisplayName !== null && requestDescription !== null) {
|
|
19264
|
+
likelyCause = `${dependencyDisplayName} failed while handling ${requestDescription}.`;
|
|
19265
|
+
recommendedAction = `Inspect the ${dependencyDisplayName} call path${frameDescription} and compare the captured dependency notes with upstream status.`;
|
|
19266
|
+
} else if (requestDescription !== null) {
|
|
19267
|
+
likelyCause = `${input.errorContext.name} occurred while handling ${requestDescription}${frameDescription}.`;
|
|
19268
|
+
recommendedAction = `Inspect the first application frame${frameDescription} and the captured request/response context.`;
|
|
19269
|
+
} else if (firstFrame !== null) {
|
|
19270
|
+
likelyCause = `${input.errorContext.name} originated from the first captured application frame${frameDescription}.`;
|
|
19271
|
+
recommendedAction = `Inspect the first application frame${frameDescription} and surrounding error handling.`;
|
|
19272
|
+
}
|
|
19273
|
+
if (likelyCause === null || recommendedAction === null) {
|
|
19274
|
+
return {
|
|
19275
|
+
likely_cause: null,
|
|
19276
|
+
confidence: 0,
|
|
19277
|
+
recommended_action: null
|
|
19278
|
+
};
|
|
19279
|
+
}
|
|
19280
|
+
let confidence = 0.25;
|
|
19281
|
+
if (input.requestContext !== null) confidence += 0.15;
|
|
19282
|
+
if (input.responseContext !== null) confidence += 0.1;
|
|
19283
|
+
if (firstFrame !== null && firstFrame.file !== null) confidence += 0.1;
|
|
19284
|
+
if (firstDependency !== null) confidence += 0.1;
|
|
19285
|
+
if (input.errorContext.message.length > 0) confidence += 0.05;
|
|
19286
|
+
return {
|
|
19287
|
+
likely_cause: likelyCause,
|
|
19288
|
+
confidence: Math.min(0.8, Number(confidence.toFixed(2))),
|
|
19289
|
+
recommended_action: recommendedAction
|
|
19290
|
+
};
|
|
19291
|
+
}
|
|
19292
|
+
function normalizeBaseUrl3(value) {
|
|
19293
|
+
const trimmed = value?.trim();
|
|
19294
|
+
if (trimmed === void 0 || trimmed.length === 0) {
|
|
19295
|
+
return null;
|
|
19296
|
+
}
|
|
19297
|
+
return trimmed.replace(/\/+$/, "");
|
|
19298
|
+
}
|
|
19299
|
+
function buildLinks(incident, linkBaseUrls) {
|
|
19300
|
+
const apiBaseUrl = normalizeBaseUrl3(linkBaseUrls?.api);
|
|
19301
|
+
const appBaseUrl = normalizeBaseUrl3(linkBaseUrls?.app);
|
|
19302
|
+
const docsBaseUrl = normalizeBaseUrl3(linkBaseUrls?.docs);
|
|
19303
|
+
const incidentPath = `/v1/incidents/${encodeURIComponent(incident.incident_id)}`;
|
|
19304
|
+
const appIncidentPath = `/incidents/${encodeURIComponent(incident.incident_id)}`;
|
|
19305
|
+
const appProjectPath = `/projects/${encodeURIComponent(incident.project_id)}`;
|
|
19306
|
+
return {
|
|
19307
|
+
self: apiBaseUrl !== null ? `${apiBaseUrl}${incidentPath}/bundle` : null,
|
|
19308
|
+
reproduction: apiBaseUrl !== null ? `${apiBaseUrl}${incidentPath}/reproduction` : null,
|
|
19309
|
+
incident: appBaseUrl !== null ? `${appBaseUrl}${appIncidentPath}` : null,
|
|
19310
|
+
project: appBaseUrl !== null ? `${appBaseUrl}${appProjectPath}` : null,
|
|
19311
|
+
docs: docsBaseUrl !== null ? `${docsBaseUrl}/bundles` : null
|
|
19312
|
+
};
|
|
19313
|
+
}
|
|
19314
|
+
function applyBundleRedaction(candidate) {
|
|
19315
|
+
const redactionResult = redact(candidate);
|
|
19316
|
+
const fields = [...new Set(redactionResult.redacted_fields)].sort();
|
|
19317
|
+
const redactedBundle = redactionResult.redacted;
|
|
19318
|
+
redactedBundle["redaction"] = {
|
|
19319
|
+
redacted: true,
|
|
19320
|
+
fields,
|
|
19321
|
+
notes: fields.length > 0 ? "Sensitive bundle fields were redacted before storage." : null
|
|
19322
|
+
};
|
|
19323
|
+
return redactedBundle;
|
|
19324
|
+
}
|
|
18925
19325
|
function buildResponseContext(envelopes) {
|
|
18926
19326
|
const requestEvent = selectLatestEnvelopeByType(envelopes, isRequestEventEnvelope);
|
|
18927
19327
|
if (requestEvent !== null) {
|
|
@@ -19054,17 +19454,31 @@ function buildFrontendContext(envelopes) {
|
|
|
19054
19454
|
dom_context: domContext
|
|
19055
19455
|
};
|
|
19056
19456
|
}
|
|
19057
|
-
function buildDeployContext(envelopes, trigger) {
|
|
19457
|
+
function buildDeployContext(envelopes, trigger, configuredDeploy) {
|
|
19058
19458
|
const envelope = selectLatestEnvelopeByType(envelopes, isDeployMetadataEnvelope);
|
|
19059
|
-
if (envelope
|
|
19459
|
+
if (envelope !== null) {
|
|
19460
|
+
return {
|
|
19461
|
+
version: 1,
|
|
19462
|
+
commit_sha: envelope.payload.commit_sha,
|
|
19463
|
+
deploy_version: envelope.payload.version,
|
|
19464
|
+
branch: envelope.payload.branch,
|
|
19465
|
+
deployed_at: toIsoTimestamp(envelope.payload.deployed_at),
|
|
19466
|
+
regression_window: trigger === "regression_reopen"
|
|
19467
|
+
};
|
|
19468
|
+
}
|
|
19469
|
+
const commitSha = configuredDeploy?.commit_sha ?? null;
|
|
19470
|
+
const deployVersion = configuredDeploy?.deploy_version ?? null;
|
|
19471
|
+
const branch = configuredDeploy?.branch ?? null;
|
|
19472
|
+
const deployedAt = configuredDeploy?.deployed_at ?? null;
|
|
19473
|
+
if (commitSha === null && deployVersion === null && branch === null && deployedAt === null) {
|
|
19060
19474
|
return null;
|
|
19061
19475
|
}
|
|
19062
19476
|
return {
|
|
19063
19477
|
version: 1,
|
|
19064
|
-
commit_sha:
|
|
19065
|
-
deploy_version:
|
|
19066
|
-
branch
|
|
19067
|
-
deployed_at: toIsoTimestamp(
|
|
19478
|
+
commit_sha: commitSha,
|
|
19479
|
+
deploy_version: deployVersion,
|
|
19480
|
+
branch,
|
|
19481
|
+
deployed_at: deployedAt === null ? null : toIsoTimestamp(deployedAt),
|
|
19068
19482
|
regression_window: trigger === "regression_reopen"
|
|
19069
19483
|
};
|
|
19070
19484
|
}
|
|
@@ -19073,34 +19487,49 @@ function buildRuntimeContext(envelopes) {
|
|
|
19073
19487
|
if (backendException === null) {
|
|
19074
19488
|
return null;
|
|
19075
19489
|
}
|
|
19490
|
+
const runtime = backendException.payload.runtime;
|
|
19076
19491
|
return {
|
|
19077
19492
|
version: 1,
|
|
19078
19493
|
name: backendException.service.runtime ?? "unknown",
|
|
19079
|
-
runtime_version:
|
|
19080
|
-
platform: null,
|
|
19081
|
-
arch: null,
|
|
19082
|
-
pid: null,
|
|
19083
|
-
cwd: null,
|
|
19084
|
-
uptime_sec: null,
|
|
19085
|
-
hostname: null,
|
|
19086
|
-
thread_id: null,
|
|
19494
|
+
runtime_version: runtime.version,
|
|
19495
|
+
platform: runtime.platform ?? null,
|
|
19496
|
+
arch: runtime.arch ?? null,
|
|
19497
|
+
pid: runtime.pid ?? null,
|
|
19498
|
+
cwd: runtime.cwd ?? null,
|
|
19499
|
+
uptime_sec: runtime.uptime_sec ?? null,
|
|
19500
|
+
hostname: runtime.hostname ?? null,
|
|
19501
|
+
thread_id: runtime.thread_id ?? null,
|
|
19087
19502
|
framework: backendException.service.framework ?? null,
|
|
19088
|
-
framework_version: null,
|
|
19089
|
-
memory: null,
|
|
19090
|
-
framework_extras: null
|
|
19503
|
+
framework_version: runtime.framework_version ?? null,
|
|
19504
|
+
memory: runtime.memory ?? null,
|
|
19505
|
+
framework_extras: runtime.framework_extras ?? null
|
|
19091
19506
|
};
|
|
19092
19507
|
}
|
|
19093
|
-
function buildGitContext(envelopes) {
|
|
19508
|
+
function buildGitContext(envelopes, configuredDeploy) {
|
|
19094
19509
|
const deployEnvelope = selectLatestEnvelopeByType(envelopes, isDeployMetadataEnvelope);
|
|
19095
19510
|
if (deployEnvelope === null) {
|
|
19096
|
-
|
|
19511
|
+
const commit = configuredDeploy?.commit_sha ?? null;
|
|
19512
|
+
const branch = configuredDeploy?.branch ?? null;
|
|
19513
|
+
const repo = configuredDeploy?.repo ?? null;
|
|
19514
|
+
if (commit === null && branch === null && repo === null) {
|
|
19515
|
+
return null;
|
|
19516
|
+
}
|
|
19517
|
+
return {
|
|
19518
|
+
version: 1,
|
|
19519
|
+
commit,
|
|
19520
|
+
commit_short: commit === null ? null : commit.slice(0, 7),
|
|
19521
|
+
branch,
|
|
19522
|
+
repo,
|
|
19523
|
+
dirty: false,
|
|
19524
|
+
source: "env"
|
|
19525
|
+
};
|
|
19097
19526
|
}
|
|
19098
19527
|
return {
|
|
19099
19528
|
version: 1,
|
|
19100
19529
|
commit: deployEnvelope.payload.commit_sha,
|
|
19101
19530
|
commit_short: deployEnvelope.payload.commit_sha.slice(0, 7),
|
|
19102
19531
|
branch: deployEnvelope.payload.branch,
|
|
19103
|
-
repo: null,
|
|
19532
|
+
repo: configuredDeploy?.repo ?? null,
|
|
19104
19533
|
dirty: false,
|
|
19105
19534
|
source: "env"
|
|
19106
19535
|
};
|
|
@@ -19143,10 +19572,11 @@ function buildBundle(input) {
|
|
|
19143
19572
|
const responseContext = buildResponseContext(sourceEnvelopes);
|
|
19144
19573
|
const logsContext = buildLogsContext(sourceEnvelopes);
|
|
19145
19574
|
const frontendContext = buildFrontendContext(sourceEnvelopes);
|
|
19146
|
-
const deployContext = buildDeployContext(sourceEnvelopes, input.job.trigger);
|
|
19575
|
+
const deployContext = buildDeployContext(sourceEnvelopes, input.job.trigger, input.configuredDeploy);
|
|
19147
19576
|
const runtimeContext = buildRuntimeContext(sourceEnvelopes);
|
|
19148
|
-
const gitContext = buildGitContext(sourceEnvelopes);
|
|
19577
|
+
const gitContext = buildGitContext(sourceEnvelopes, input.configuredDeploy);
|
|
19149
19578
|
const deviceContext = buildDeviceContext(sourceEnvelopes);
|
|
19579
|
+
const dependenciesContext = buildDependenciesContext(input.incident, errorContext, requestContext);
|
|
19150
19580
|
const primarySignalType = primarySignalEnvelope !== null ? mapSignalType(primarySignalEnvelope.event_type) : inferSignalTypeFromSourceEventTypes(sourceEventTypes);
|
|
19151
19581
|
const primarySourceEvent = errorContext?.name ?? sourceEventTypes[0] ?? "backend_exception";
|
|
19152
19582
|
const firstSeenAt = new Date(input.incident.first_seen_at).toISOString();
|
|
@@ -19155,7 +19585,15 @@ function buildBundle(input) {
|
|
|
19155
19585
|
const serviceRuntime = input.incident.service_runtime ?? selectLatestEnvelope(sourceEnvelopes, (envelope) => envelope.event_type !== "probe_event")?.service.runtime ?? null;
|
|
19156
19586
|
const serviceFramework = input.incident.service_framework ?? selectLatestEnvelope(sourceEnvelopes, (envelope) => envelope.event_type !== "probe_event")?.service.framework ?? null;
|
|
19157
19587
|
const customerVisible = frontendContext !== null;
|
|
19158
|
-
|
|
19588
|
+
const firstApplicationFrame = deriveFirstApplicationFrame(errorContext);
|
|
19589
|
+
const summaryGuidance = buildSummaryGuidance({
|
|
19590
|
+
errorContext,
|
|
19591
|
+
requestContext,
|
|
19592
|
+
responseContext,
|
|
19593
|
+
dependenciesContext,
|
|
19594
|
+
firstApplicationFrame
|
|
19595
|
+
});
|
|
19596
|
+
const candidate = {
|
|
19159
19597
|
bundle_version: 1,
|
|
19160
19598
|
bundle_id: `bnd_${input.incident.incident_id}`,
|
|
19161
19599
|
bundle_type: "failure",
|
|
@@ -19190,13 +19628,13 @@ function buildBundle(input) {
|
|
|
19190
19628
|
summary: {
|
|
19191
19629
|
title: input.incident.title,
|
|
19192
19630
|
description: `Deterministic bundle generated from ${input.job.trigger}`,
|
|
19193
|
-
likely_cause:
|
|
19194
|
-
confidence:
|
|
19195
|
-
recommended_action:
|
|
19631
|
+
likely_cause: summaryGuidance.likely_cause,
|
|
19632
|
+
confidence: summaryGuidance.confidence,
|
|
19633
|
+
recommended_action: summaryGuidance.recommended_action,
|
|
19196
19634
|
severity: input.incident.severity,
|
|
19197
19635
|
error_type: primarySourceEvent,
|
|
19198
19636
|
error_message: errorContext?.message ?? input.incident.title,
|
|
19199
|
-
first_application_frame:
|
|
19637
|
+
first_application_frame: firstApplicationFrame,
|
|
19200
19638
|
primary_signal: primarySignalType,
|
|
19201
19639
|
signals: {
|
|
19202
19640
|
new_deploy: input.job.trigger === "deploy_metadata",
|
|
@@ -19221,7 +19659,7 @@ function buildBundle(input) {
|
|
|
19221
19659
|
deploy: deployContext,
|
|
19222
19660
|
runtime: runtimeContext,
|
|
19223
19661
|
git: gitContext,
|
|
19224
|
-
dependencies:
|
|
19662
|
+
dependencies: dependenciesContext,
|
|
19225
19663
|
probe_data: {
|
|
19226
19664
|
version: 1,
|
|
19227
19665
|
items: input.probeDataItems
|
|
@@ -19242,11 +19680,7 @@ function buildBundle(input) {
|
|
|
19242
19680
|
production_verified: false
|
|
19243
19681
|
},
|
|
19244
19682
|
links: {
|
|
19245
|
-
|
|
19246
|
-
reproduction: null,
|
|
19247
|
-
incident: null,
|
|
19248
|
-
project: null,
|
|
19249
|
-
docs: null
|
|
19683
|
+
...buildLinks(input.incident, input.linkBaseUrls)
|
|
19250
19684
|
},
|
|
19251
19685
|
redaction: {
|
|
19252
19686
|
redacted: true,
|
|
@@ -19259,7 +19693,8 @@ function buildBundle(input) {
|
|
|
19259
19693
|
generator_version: "worker-build-bundle-v2",
|
|
19260
19694
|
generation_number: input.bundleMetadata.generation_number
|
|
19261
19695
|
}
|
|
19262
|
-
}
|
|
19696
|
+
};
|
|
19697
|
+
return BundleV1Schema.parse(applyBundleRedaction(candidate));
|
|
19263
19698
|
}
|
|
19264
19699
|
|
|
19265
19700
|
// ../../packages/repro-engine/src/index.ts
|
|
@@ -19279,6 +19714,44 @@ function shellQuote(value) {
|
|
|
19279
19714
|
function sortRecordEntries(record) {
|
|
19280
19715
|
return Object.entries(record).sort(([left], [right]) => left.localeCompare(right));
|
|
19281
19716
|
}
|
|
19717
|
+
var REPLAY_HEADER_PRIORITY = [
|
|
19718
|
+
"authorization",
|
|
19719
|
+
"cookie",
|
|
19720
|
+
"accept",
|
|
19721
|
+
"content-type",
|
|
19722
|
+
"origin",
|
|
19723
|
+
"accept-language",
|
|
19724
|
+
"access-control-request-method",
|
|
19725
|
+
"access-control-request-headers",
|
|
19726
|
+
"x-request-id",
|
|
19727
|
+
"x-correlation-id",
|
|
19728
|
+
"x-debugbundle-trace-id"
|
|
19729
|
+
];
|
|
19730
|
+
var DROPPED_REPLAY_HEADERS = /* @__PURE__ */ new Set([
|
|
19731
|
+
"host",
|
|
19732
|
+
"x-forwarded-host",
|
|
19733
|
+
"x-forwarded-proto",
|
|
19734
|
+
"connection",
|
|
19735
|
+
"keep-alive",
|
|
19736
|
+
"transfer-encoding",
|
|
19737
|
+
"upgrade",
|
|
19738
|
+
"te",
|
|
19739
|
+
"trailer",
|
|
19740
|
+
"proxy-connection",
|
|
19741
|
+
"accept-encoding",
|
|
19742
|
+
"content-length",
|
|
19743
|
+
"cache-control",
|
|
19744
|
+
"pragma",
|
|
19745
|
+
"priority",
|
|
19746
|
+
"sec-ch-ua",
|
|
19747
|
+
"sec-ch-ua-mobile",
|
|
19748
|
+
"sec-ch-ua-platform",
|
|
19749
|
+
"sec-fetch-dest",
|
|
19750
|
+
"sec-fetch-mode",
|
|
19751
|
+
"sec-fetch-site",
|
|
19752
|
+
"sec-fetch-user",
|
|
19753
|
+
"user-agent"
|
|
19754
|
+
]);
|
|
19282
19755
|
function serializeScalarValue(value) {
|
|
19283
19756
|
if (typeof value === "string") {
|
|
19284
19757
|
return value;
|
|
@@ -19357,12 +19830,25 @@ function buildStructuredReplayQuery(query) {
|
|
|
19357
19830
|
return hasStructuredQueryAmbiguity(normalizedQuery) ? normalizedQuery : void 0;
|
|
19358
19831
|
}
|
|
19359
19832
|
function buildReplayHeaders(headers) {
|
|
19360
|
-
|
|
19361
|
-
|
|
19362
|
-
|
|
19833
|
+
const entries = sortRecordEntries(headers).filter(([headerName]) => !DROPPED_REPLAY_HEADERS.has(headerName.toLowerCase())).map(([headerName, headerValue]) => [headerName, normalizeHeaderValue(headerValue)]);
|
|
19834
|
+
entries.sort(([left], [right]) => {
|
|
19835
|
+
const leftPriority = REPLAY_HEADER_PRIORITY.indexOf(left.toLowerCase());
|
|
19836
|
+
const rightPriority = REPLAY_HEADER_PRIORITY.indexOf(right.toLowerCase());
|
|
19837
|
+
if (leftPriority !== -1 || rightPriority !== -1) {
|
|
19838
|
+
if (leftPriority === -1) {
|
|
19839
|
+
return 1;
|
|
19840
|
+
}
|
|
19841
|
+
if (rightPriority === -1) {
|
|
19842
|
+
return -1;
|
|
19843
|
+
}
|
|
19844
|
+
return leftPriority - rightPriority;
|
|
19845
|
+
}
|
|
19846
|
+
return left.localeCompare(right);
|
|
19847
|
+
});
|
|
19848
|
+
return Object.fromEntries(entries);
|
|
19363
19849
|
}
|
|
19364
19850
|
function expandHeaderValues(headers) {
|
|
19365
|
-
return
|
|
19851
|
+
return Object.entries(headers).flatMap(([headerName, headerValue]) => {
|
|
19366
19852
|
if (Array.isArray(headerValue)) {
|
|
19367
19853
|
return headerValue.map((item) => [headerName, serializeScalarValue(item)]);
|
|
19368
19854
|
}
|
|
@@ -19512,11 +19998,17 @@ var EVENT_TYPE_SET = new Set(EventTypeValues);
|
|
|
19512
19998
|
function isEventType(value) {
|
|
19513
19999
|
return typeof value === "string" && EVENT_TYPE_SET.has(value);
|
|
19514
20000
|
}
|
|
19515
|
-
function inferSeverity2(
|
|
19516
|
-
if (
|
|
20001
|
+
function inferSeverity2(event, capturePreset, incidentKind = "immediate") {
|
|
20002
|
+
if (incidentKind === "request_anomaly") {
|
|
20003
|
+
return "medium";
|
|
20004
|
+
}
|
|
20005
|
+
if (event.event_type === "request_event") {
|
|
20006
|
+
return classifyRequestStatus({ responseStatus: event.payload.response_status, capturePreset }) === "incident_signal" ? "high" : "low";
|
|
20007
|
+
}
|
|
20008
|
+
if (event.event_type === "backend_exception" || event.event_type === "frontend_exception") {
|
|
19517
20009
|
return "high";
|
|
19518
20010
|
}
|
|
19519
|
-
if (
|
|
20011
|
+
if (event.event_type === "error_suppressed") {
|
|
19520
20012
|
return "medium";
|
|
19521
20013
|
}
|
|
19522
20014
|
return "low";
|
|
@@ -19540,15 +20032,17 @@ function compareEventEnvelopes(left, right) {
|
|
|
19540
20032
|
}
|
|
19541
20033
|
return left.event_id.localeCompare(right.event_id);
|
|
19542
20034
|
}
|
|
19543
|
-
function classifyEnvelope(envelope) {
|
|
20035
|
+
function classifyEnvelope(envelope, capturePreset) {
|
|
19544
20036
|
return classifyEvent(
|
|
19545
20037
|
envelope.event_type,
|
|
19546
20038
|
envelope.event_type === "log_event" ? envelope.payload.level : void 0,
|
|
19547
|
-
envelope.event_type === "probe_event" ? envelope.payload.activation_id : void 0
|
|
20039
|
+
envelope.event_type === "probe_event" ? envelope.payload.activation_id : void 0,
|
|
20040
|
+
envelope.payload,
|
|
20041
|
+
capturePreset
|
|
19548
20042
|
);
|
|
19549
20043
|
}
|
|
19550
|
-
function isIncidentSignalEnvelope(envelope) {
|
|
19551
|
-
return classifyEnvelope(envelope) === "incident_signal";
|
|
20044
|
+
function isIncidentSignalEnvelope(envelope, capturePreset) {
|
|
20045
|
+
return classifyEnvelope(envelope, capturePreset) === "incident_signal";
|
|
19552
20046
|
}
|
|
19553
20047
|
function getTraceId(envelope) {
|
|
19554
20048
|
return envelope.correlation?.trace_id ?? null;
|
|
@@ -19593,7 +20087,10 @@ function mergeAggregateGroup(aggregates) {
|
|
|
19593
20087
|
newEvents: [...canonicalAggregate.newEvents],
|
|
19594
20088
|
mergedIncidentIds: new Set(canonicalAggregate.mergedIncidentIds),
|
|
19595
20089
|
signalEventTypes: new Set(canonicalAggregate.signalEventTypes),
|
|
19596
|
-
traceIds: new Set(canonicalAggregate.traceIds)
|
|
20090
|
+
traceIds: new Set(canonicalAggregate.traceIds),
|
|
20091
|
+
title: canonicalAggregate.title,
|
|
20092
|
+
kind: canonicalAggregate.kind,
|
|
20093
|
+
severity: canonicalAggregate.severity
|
|
19597
20094
|
});
|
|
19598
20095
|
}
|
|
19599
20096
|
function hashIdentifier(parts, prefix, length) {
|
|
@@ -19619,6 +20116,111 @@ function mergeSourceEvents(existingEvents, nextEvents) {
|
|
|
19619
20116
|
}
|
|
19620
20117
|
return [...merged.values()].sort(compareEventEnvelopes);
|
|
19621
20118
|
}
|
|
20119
|
+
function stableJson2(value) {
|
|
20120
|
+
if (value === null || typeof value !== "object") {
|
|
20121
|
+
return JSON.stringify(value);
|
|
20122
|
+
}
|
|
20123
|
+
if (Array.isArray(value)) {
|
|
20124
|
+
return `[${value.map((entry) => stableJson2(entry)).join(",")}]`;
|
|
20125
|
+
}
|
|
20126
|
+
const record = value;
|
|
20127
|
+
const keys = Object.keys(record).sort();
|
|
20128
|
+
return `{${keys.map((key) => `${JSON.stringify(key)}:${stableJson2(record[key])}`).join(",")}}`;
|
|
20129
|
+
}
|
|
20130
|
+
function buildRequestAnomalyFingerprint(input) {
|
|
20131
|
+
return (0, import_node_crypto4.createHash)("sha256").update(
|
|
20132
|
+
stableJson2({
|
|
20133
|
+
kind: "request_status_anomaly",
|
|
20134
|
+
project_id: input.projectId,
|
|
20135
|
+
service_name: input.serviceName,
|
|
20136
|
+
environment: input.environment,
|
|
20137
|
+
method: input.method,
|
|
20138
|
+
route_template: input.routeTemplate,
|
|
20139
|
+
response_status: input.responseStatus
|
|
20140
|
+
})
|
|
20141
|
+
).digest("hex");
|
|
20142
|
+
}
|
|
20143
|
+
function buildRequestAnomalyTitle(input) {
|
|
20144
|
+
return `Request anomaly: ${input.method} ${input.routeTemplate} returned ${input.responseStatus} repeatedly`;
|
|
20145
|
+
}
|
|
20146
|
+
function toUnixSeconds(occurredAt) {
|
|
20147
|
+
return Math.floor(new Date(occurredAt).getTime() / 1e3);
|
|
20148
|
+
}
|
|
20149
|
+
function countOccurrencesInWindow(events, windowSeconds) {
|
|
20150
|
+
const latestEvent = events.at(-1);
|
|
20151
|
+
if (latestEvent === void 0) {
|
|
20152
|
+
return 0;
|
|
20153
|
+
}
|
|
20154
|
+
const latestOccurredAt = toUnixSeconds(latestEvent.occurred_at);
|
|
20155
|
+
const lowerBound = latestOccurredAt - windowSeconds + 1;
|
|
20156
|
+
return events.filter((event) => {
|
|
20157
|
+
const occurredAt = toUnixSeconds(event.occurred_at);
|
|
20158
|
+
return occurredAt >= lowerBound && occurredAt <= latestOccurredAt;
|
|
20159
|
+
}).length;
|
|
20160
|
+
}
|
|
20161
|
+
function passesRequestAnomalyThreshold(events, threshold) {
|
|
20162
|
+
const occurrences5m = countOccurrencesInWindow(events, 5 * 60);
|
|
20163
|
+
const occurrences1h = countOccurrencesInWindow(events, 60 * 60);
|
|
20164
|
+
const baseline1hPer5m = occurrences1h / 12;
|
|
20165
|
+
const ratio = occurrences5m / Math.max(baseline1hPer5m, 1);
|
|
20166
|
+
return occurrences5m >= threshold.minimum_occurrences_5m && ratio >= threshold.minimum_ratio_5m_to_1h;
|
|
20167
|
+
}
|
|
20168
|
+
function collectRequestAnomalyAggregates(batches, capturePreset) {
|
|
20169
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
20170
|
+
for (const batch of batches) {
|
|
20171
|
+
for (const event of batch.events) {
|
|
20172
|
+
if (event.event_type !== "request_event" || classifyEnvelope(event, capturePreset) !== "context_signal") {
|
|
20173
|
+
continue;
|
|
20174
|
+
}
|
|
20175
|
+
const normalizedEvent = normalizeEvent(event);
|
|
20176
|
+
const responseStatus = normalizedEvent.http_status;
|
|
20177
|
+
const method = normalizedEvent.http_method;
|
|
20178
|
+
const routeTemplate = normalizedEvent.route_template;
|
|
20179
|
+
const threshold = getRequestAnomalyThreshold({ responseStatus, capturePreset });
|
|
20180
|
+
if (threshold === null || responseStatus === null || method === null || routeTemplate === null) {
|
|
20181
|
+
continue;
|
|
20182
|
+
}
|
|
20183
|
+
const projectId = requireProjectId(event);
|
|
20184
|
+
const incidentFingerprint = buildRequestAnomalyFingerprint({
|
|
20185
|
+
projectId,
|
|
20186
|
+
serviceName: event.service.name,
|
|
20187
|
+
environment: event.service.environment,
|
|
20188
|
+
method,
|
|
20189
|
+
routeTemplate,
|
|
20190
|
+
responseStatus
|
|
20191
|
+
});
|
|
20192
|
+
const incidentId = deriveIncidentId(projectId, event.service.name, event.service.environment, incidentFingerprint);
|
|
20193
|
+
const aggregate = grouped.get(incidentId) ?? {
|
|
20194
|
+
incidentId,
|
|
20195
|
+
projectId,
|
|
20196
|
+
serviceName: event.service.name,
|
|
20197
|
+
environment: event.service.environment,
|
|
20198
|
+
fingerprint: incidentFingerprint,
|
|
20199
|
+
matchedFields: /* @__PURE__ */ new Set(["request_anomaly", "route_template", "http_method", "http_status", "environment"]),
|
|
20200
|
+
newEvents: [],
|
|
20201
|
+
mergedIncidentIds: /* @__PURE__ */ new Set([incidentId]),
|
|
20202
|
+
signalEventTypes: /* @__PURE__ */ new Set(["request_event"]),
|
|
20203
|
+
traceIds: /* @__PURE__ */ new Set(),
|
|
20204
|
+
title: buildRequestAnomalyTitle({ method, routeTemplate, responseStatus }),
|
|
20205
|
+
kind: "request_anomaly",
|
|
20206
|
+
severity: "medium"
|
|
20207
|
+
};
|
|
20208
|
+
aggregate.newEvents.push(event);
|
|
20209
|
+
grouped.set(incidentId, aggregate);
|
|
20210
|
+
}
|
|
20211
|
+
}
|
|
20212
|
+
return [...grouped.values()].filter((aggregate) => {
|
|
20213
|
+
const latestEvent = aggregate.newEvents.at(-1);
|
|
20214
|
+
if (latestEvent === void 0 || latestEvent.event_type !== "request_event") {
|
|
20215
|
+
return false;
|
|
20216
|
+
}
|
|
20217
|
+
const threshold = getRequestAnomalyThreshold({
|
|
20218
|
+
responseStatus: normalizeEvent(latestEvent).http_status,
|
|
20219
|
+
capturePreset
|
|
20220
|
+
});
|
|
20221
|
+
return threshold !== null && passesRequestAnomalyThreshold(aggregate.newEvents, threshold);
|
|
20222
|
+
}).sort((left, right) => left.incidentId.localeCompare(right.incidentId));
|
|
20223
|
+
}
|
|
19622
20224
|
function buildBundleContext(incident) {
|
|
19623
20225
|
return {
|
|
19624
20226
|
incident_id: incident.incident_id,
|
|
@@ -19648,12 +20250,12 @@ function formatServiceSummary(services) {
|
|
|
19648
20250
|
}
|
|
19649
20251
|
function formatProcessOutput(summary) {
|
|
19650
20252
|
if (!summary.processed) {
|
|
19651
|
-
return summary.message
|
|
20253
|
+
return summary.message;
|
|
19652
20254
|
}
|
|
19653
20255
|
return [
|
|
19654
20256
|
`Processed ${summary.events_processed} events from ${summary.files_processed} files into ${summary.incidents_processed} incidents.`,
|
|
19655
20257
|
...formatServiceSummary(summary.services),
|
|
19656
|
-
`Last processed event file: ${summary.last_processed_event_file
|
|
20258
|
+
`Last processed event file: ${summary.last_processed_event_file}`
|
|
19657
20259
|
].join("\n");
|
|
19658
20260
|
}
|
|
19659
20261
|
async function pathExists4(path, stat) {
|
|
@@ -19893,6 +20495,7 @@ async function processCommand(input, dependencies = {}) {
|
|
|
19893
20495
|
const statePath = (0, import_node_path6.join)(rootDirectory, LOCAL_STATE_FILE_PATH);
|
|
19894
20496
|
const bundleDirectoryPath = (0, import_node_path6.join)(rootDirectory, LOCAL_BUNDLE_DIRECTORY_PATH2);
|
|
19895
20497
|
const reproductionDirectoryPath = (0, import_node_path6.join)(rootDirectory, LOCAL_REPRODUCTION_DIRECTORY_PATH);
|
|
20498
|
+
const capturePreset = input.preset ?? "minimal";
|
|
19896
20499
|
await mkdir((0, import_node_path6.join)(rootDirectory, ".debugbundle", "local"), { recursive: true });
|
|
19897
20500
|
await mkdir(bundleDirectoryPath, { recursive: true });
|
|
19898
20501
|
await mkdir(reproductionDirectoryPath, { recursive: true });
|
|
@@ -19900,22 +20503,26 @@ async function processCommand(input, dependencies = {}) {
|
|
|
19900
20503
|
const eventFileNames = await pathExists4(eventsDirectoryPath, stat) ? (await readdir(eventsDirectoryPath)).filter((fileName) => fileName.endsWith(".events.json")).sort() : [];
|
|
19901
20504
|
const lastProcessedEventFile = previousState?.last_processed_event_file ?? null;
|
|
19902
20505
|
const newEventFileNames = lastProcessedEventFile === null ? eventFileNames : eventFileNames.filter((fileName) => fileName > lastProcessedEventFile);
|
|
19903
|
-
|
|
20506
|
+
const processAllEventFiles = input.preset !== void 0;
|
|
20507
|
+
const targetEventFileNames = processAllEventFiles ? eventFileNames : newEventFileNames;
|
|
20508
|
+
if (targetEventFileNames.length === 0) {
|
|
19904
20509
|
const summary2 = buildNoNewEventsSummary(previousState?.last_processed_event_file ?? eventFileNames.at(-1) ?? null);
|
|
19905
20510
|
return {
|
|
19906
20511
|
exitCode: 0,
|
|
19907
20512
|
output: input.json === true ? JSON.stringify(summary2) : formatProcessOutput(summary2)
|
|
19908
20513
|
};
|
|
19909
20514
|
}
|
|
19910
|
-
const batches = await readEventBatches(eventsDirectoryPath,
|
|
19911
|
-
const incidents = new Map(
|
|
20515
|
+
const batches = await readEventBatches(eventsDirectoryPath, targetEventFileNames, readFile);
|
|
20516
|
+
const incidents = new Map(
|
|
20517
|
+
processAllEventFiles ? [] : Object.entries(previousState?.incidents ?? {})
|
|
20518
|
+
);
|
|
19912
20519
|
const aggregates = /* @__PURE__ */ new Map();
|
|
19913
20520
|
const traceCorrelationGroups = /* @__PURE__ */ new Map();
|
|
19914
20521
|
let eventsProcessed = 0;
|
|
19915
20522
|
for (const batch of batches) {
|
|
19916
20523
|
for (const event of batch.events) {
|
|
19917
20524
|
eventsProcessed += 1;
|
|
19918
|
-
if (!isIncidentSignalEnvelope(event)) {
|
|
20525
|
+
if (!isIncidentSignalEnvelope(event, capturePreset)) {
|
|
19919
20526
|
continue;
|
|
19920
20527
|
}
|
|
19921
20528
|
const normalizedEvent = normalizeEvent(event);
|
|
@@ -19932,7 +20539,10 @@ async function processCommand(input, dependencies = {}) {
|
|
|
19932
20539
|
newEvents: [],
|
|
19933
20540
|
mergedIncidentIds: /* @__PURE__ */ new Set([incidentId]),
|
|
19934
20541
|
signalEventTypes: /* @__PURE__ */ new Set(),
|
|
19935
|
-
traceIds: /* @__PURE__ */ new Set()
|
|
20542
|
+
traceIds: /* @__PURE__ */ new Set(),
|
|
20543
|
+
title: normalizedEvent.normalized_message,
|
|
20544
|
+
kind: "immediate",
|
|
20545
|
+
severity: inferSeverity2(event, capturePreset)
|
|
19936
20546
|
};
|
|
19937
20547
|
for (const matchedField of inferMatchedFields(normalizedEvent)) {
|
|
19938
20548
|
aggregate.matchedFields.add(matchedField);
|
|
@@ -19999,14 +20609,16 @@ async function processCommand(input, dependencies = {}) {
|
|
|
19999
20609
|
mergedAggregatesByRoot.set(rootIncidentId, aggregateGroup);
|
|
20000
20610
|
}
|
|
20001
20611
|
const mergedAggregates = [...mergedAggregatesByRoot.values()].map((aggregateGroup) => mergeAggregateGroup(aggregateGroup)).sort((left, right) => left.incidentId.localeCompare(right.incidentId));
|
|
20612
|
+
const requestAnomalyAggregates = input.preset === void 0 ? [] : collectRequestAnomalyAggregates(batches, capturePreset);
|
|
20613
|
+
const finalizedAggregates = [...mergedAggregates, ...requestAnomalyAggregates].sort((left, right) => left.incidentId.localeCompare(right.incidentId));
|
|
20002
20614
|
const services = /* @__PURE__ */ new Map();
|
|
20003
|
-
for (const aggregate of
|
|
20615
|
+
for (const aggregate of finalizedAggregates) {
|
|
20004
20616
|
const incidentId = aggregate.incidentId;
|
|
20005
20617
|
const existingIncidents = [...aggregate.mergedIncidentIds].map((mergedIncidentId) => incidents.get(mergedIncidentId)).filter((incident2) => incident2 !== void 0);
|
|
20006
20618
|
const existing = existingIncidents.find((incident2) => incident2.incident_id === incidentId) ?? existingIncidents[0];
|
|
20007
20619
|
const existingSourceEvents = existingIncidents.flatMap((incident2) => incident2.source_events);
|
|
20008
20620
|
const combinedSourceEvents = mergeSourceEvents(existingSourceEvents, aggregate.newEvents);
|
|
20009
|
-
const signalEvents = combinedSourceEvents.filter(isIncidentSignalEnvelope);
|
|
20621
|
+
const signalEvents = aggregate.kind === "request_anomaly" ? combinedSourceEvents : combinedSourceEvents.filter((event) => isIncidentSignalEnvelope(event, capturePreset));
|
|
20010
20622
|
if (signalEvents.length === 0) {
|
|
20011
20623
|
continue;
|
|
20012
20624
|
}
|
|
@@ -20016,8 +20628,7 @@ async function processCommand(input, dependencies = {}) {
|
|
|
20016
20628
|
continue;
|
|
20017
20629
|
}
|
|
20018
20630
|
const sourceEventTypes = [...new Set(signalEvents.map((event) => event.event_type))].sort();
|
|
20019
|
-
const severity = signalEvents.map((event) => inferSeverity2(event.
|
|
20020
|
-
const latestNormalizedEvent = normalizeEvent(latestSignalEvent);
|
|
20631
|
+
const severity = signalEvents.map((event) => inferSeverity2(event, capturePreset, aggregate.kind)).sort((left, right) => severityRank(right) - severityRank(left))[0] ?? aggregate.severity;
|
|
20021
20632
|
const generationNumber = signalEvents.length;
|
|
20022
20633
|
const bundlePath = `${LOCAL_BUNDLE_DIRECTORY_PATH2}/${incidentId}.bundle.json`;
|
|
20023
20634
|
const reproductionPath = `${LOCAL_REPRODUCTION_DIRECTORY_PATH}/${incidentId}.reproduction.json`;
|
|
@@ -20032,7 +20643,7 @@ async function processCommand(input, dependencies = {}) {
|
|
|
20032
20643
|
environment: aggregate.environment,
|
|
20033
20644
|
fingerprint: aggregate.fingerprint,
|
|
20034
20645
|
fingerprint_version: FINGERPRINT_VERSION,
|
|
20035
|
-
title:
|
|
20646
|
+
title: aggregate.title,
|
|
20036
20647
|
severity,
|
|
20037
20648
|
status: existingIncidents.some((incidentState) => incidentState.status === "resolved") ? "open" : existing?.status ?? "open",
|
|
20038
20649
|
first_seen_at: firstSignalEvent.occurred_at,
|
|
@@ -20093,21 +20704,22 @@ async function processCommand(input, dependencies = {}) {
|
|
|
20093
20704
|
incidents.set(incidentId, incident);
|
|
20094
20705
|
services.set(incident.service_name, (services.get(incident.service_name) ?? 0) + 1);
|
|
20095
20706
|
}
|
|
20707
|
+
const finalProcessedEventFile = targetEventFileNames[targetEventFileNames.length - 1];
|
|
20096
20708
|
const nextState = {
|
|
20097
20709
|
version: 1,
|
|
20098
|
-
last_processed_event_file:
|
|
20710
|
+
last_processed_event_file: finalProcessedEventFile,
|
|
20099
20711
|
incidents: Object.fromEntries([...incidents.entries()].sort(([left], [right]) => left.localeCompare(right)))
|
|
20100
20712
|
};
|
|
20101
20713
|
await writeFile(statePath, serializeState(nextState));
|
|
20102
20714
|
const summary = buildProcessedSummary({
|
|
20103
20715
|
filesProcessed: newEventFileNames.length,
|
|
20104
20716
|
eventsProcessed,
|
|
20105
|
-
incidentsProcessed:
|
|
20717
|
+
incidentsProcessed: finalizedAggregates.length,
|
|
20106
20718
|
services: [...services.entries()].sort(([left], [right]) => left.localeCompare(right)).map(([service, count]) => ({
|
|
20107
20719
|
service,
|
|
20108
20720
|
incidents: count
|
|
20109
20721
|
})),
|
|
20110
|
-
lastProcessedEventFile:
|
|
20722
|
+
lastProcessedEventFile: finalProcessedEventFile
|
|
20111
20723
|
});
|
|
20112
20724
|
return {
|
|
20113
20725
|
exitCode: 0,
|
|
@@ -20223,7 +20835,11 @@ function parseLocalIncident(candidate) {
|
|
|
20223
20835
|
}
|
|
20224
20836
|
const serviceRuntime = candidate["service_runtime"];
|
|
20225
20837
|
const serviceFramework = candidate["service_framework"];
|
|
20226
|
-
const incidentReason =
|
|
20838
|
+
const incidentReason = candidate["matched_fields"].includes("request_anomaly") ? deriveIncidentReasonFromSignal({
|
|
20839
|
+
event_type: "request_event",
|
|
20840
|
+
event_class: "incident_signal",
|
|
20841
|
+
request_anomaly: true
|
|
20842
|
+
}) : deriveIncidentReasonFromSourceEventTypes(candidate["source_event_types"]);
|
|
20227
20843
|
if (serviceRuntime !== null && typeof serviceRuntime !== "string") {
|
|
20228
20844
|
throw createReadError(400, "invalid_local_state");
|
|
20229
20845
|
}
|
|
@@ -20472,7 +21088,7 @@ function buildCloudSuggestedActions(status, incidentId, mode = "passive_recent_i
|
|
|
20472
21088
|
];
|
|
20473
21089
|
}
|
|
20474
21090
|
return [
|
|
20475
|
-
"Run debugbundle login to create ~/.debugbundle/auth.json before verifying cloud traffic.",
|
|
21091
|
+
"Run debugbundle login to choose an auth flow, or use debugbundle login --github, debugbundle login --github-device, or debugbundle login <dbundle_mem_...> to create ~/.debugbundle/auth.json before verifying cloud traffic.",
|
|
20476
21092
|
"Generate a live cloud request, then re-run debugbundle verify cloud with the correct project and service filters."
|
|
20477
21093
|
];
|
|
20478
21094
|
}
|
|
@@ -20529,14 +21145,14 @@ function localFailureStepName(checks) {
|
|
|
20529
21145
|
function cloudVerificationRunId(now) {
|
|
20530
21146
|
return now.toISOString().replace(/[-:.TZ]/g, "").slice(0, 14);
|
|
20531
21147
|
}
|
|
20532
|
-
function
|
|
21148
|
+
function requestFailureReason() {
|
|
20533
21149
|
const incidentReason = deriveIncidentReasonFromSignal({
|
|
20534
21150
|
event_type: "request_event",
|
|
20535
21151
|
event_class: "incident_signal",
|
|
20536
21152
|
response_status: 503
|
|
20537
21153
|
});
|
|
20538
21154
|
if (incidentReason === null) {
|
|
20539
|
-
throw new Error("
|
|
21155
|
+
throw new Error("request_failure_reason_unavailable");
|
|
20540
21156
|
}
|
|
20541
21157
|
return incidentReason;
|
|
20542
21158
|
}
|
|
@@ -20811,7 +21427,7 @@ async function verifyCloudCommand(input, dependencies = {}) {
|
|
|
20811
21427
|
const verification = {
|
|
20812
21428
|
mode: "active_5xx",
|
|
20813
21429
|
bundle_status: "unknown",
|
|
20814
|
-
classification_reason:
|
|
21430
|
+
classification_reason: requestFailureReason()
|
|
20815
21431
|
};
|
|
20816
21432
|
const errors = [];
|
|
20817
21433
|
let exitCode = 0;
|
|
@@ -20863,7 +21479,7 @@ async function verifyCloudCommand(input, dependencies = {}) {
|
|
|
20863
21479
|
if (candidate !== void 0) {
|
|
20864
21480
|
incidentId = candidate.incident_id;
|
|
20865
21481
|
verification.incident_id = candidate.incident_id;
|
|
20866
|
-
verification.classification_reason = candidate.incident_reason ??
|
|
21482
|
+
verification.classification_reason = candidate.incident_reason ?? requestFailureReason();
|
|
20867
21483
|
break;
|
|
20868
21484
|
}
|
|
20869
21485
|
if (attempt < pollAttempts) {
|
|
@@ -21359,7 +21975,8 @@ function createAlertMcpTools(api) {
|
|
|
21359
21975
|
bearerToken: String(input["bearerToken"]),
|
|
21360
21976
|
projectId: String(input["projectId"]),
|
|
21361
21977
|
channel: String(input["channel"]),
|
|
21362
|
-
conditionType: String(input["conditionType"])
|
|
21978
|
+
conditionType: String(input["conditionType"]),
|
|
21979
|
+
config: input["config"]
|
|
21363
21980
|
};
|
|
21364
21981
|
if (typeof input["serviceId"] === "string") {
|
|
21365
21982
|
requestInput.serviceId = input["serviceId"];
|
|
@@ -21367,9 +21984,6 @@ function createAlertMcpTools(api) {
|
|
|
21367
21984
|
if (typeof input["severityMin"] === "string") {
|
|
21368
21985
|
requestInput.severityMin = input["severityMin"];
|
|
21369
21986
|
}
|
|
21370
|
-
if (typeof input["config"] === "object" && input["config"] !== null) {
|
|
21371
|
-
requestInput.config = input["config"];
|
|
21372
|
-
}
|
|
21373
21987
|
if (typeof input["isEnabled"] === "boolean") {
|
|
21374
21988
|
requestInput.isEnabled = input["isEnabled"];
|
|
21375
21989
|
}
|
|
@@ -22642,8 +23256,71 @@ function createSetupMcpTools(commands) {
|
|
|
22642
23256
|
};
|
|
22643
23257
|
}
|
|
22644
23258
|
|
|
22645
|
-
// src/
|
|
23259
|
+
// src/slack-tools.ts
|
|
22646
23260
|
function mapMcpError12(error) {
|
|
23261
|
+
if (error instanceof SlackApiError) {
|
|
23262
|
+
throw new Error(`mcp_tool_error:${error.code}`);
|
|
23263
|
+
}
|
|
23264
|
+
throw new Error("mcp_tool_error:unknown_error");
|
|
23265
|
+
}
|
|
23266
|
+
function createSlackMcpTools(api) {
|
|
23267
|
+
return {
|
|
23268
|
+
async list_slack_destinations(input) {
|
|
23269
|
+
try {
|
|
23270
|
+
return {
|
|
23271
|
+
destinations: await api.listSlackDestinations({
|
|
23272
|
+
bearerToken: String(input["bearerToken"]),
|
|
23273
|
+
projectId: String(input["projectId"])
|
|
23274
|
+
})
|
|
23275
|
+
};
|
|
23276
|
+
} catch (error) {
|
|
23277
|
+
mapMcpError12(error);
|
|
23278
|
+
}
|
|
23279
|
+
},
|
|
23280
|
+
async get_slack_connect_url(input) {
|
|
23281
|
+
try {
|
|
23282
|
+
return {
|
|
23283
|
+
install_url: await api.getSlackInstallUrl({
|
|
23284
|
+
bearerToken: String(input["bearerToken"]),
|
|
23285
|
+
projectId: String(input["projectId"]),
|
|
23286
|
+
...typeof input["returnTo"] === "string" ? { returnTo: input["returnTo"] } : {}
|
|
23287
|
+
})
|
|
23288
|
+
};
|
|
23289
|
+
} catch (error) {
|
|
23290
|
+
mapMcpError12(error);
|
|
23291
|
+
}
|
|
23292
|
+
},
|
|
23293
|
+
async test_slack_destination(input) {
|
|
23294
|
+
try {
|
|
23295
|
+
return {
|
|
23296
|
+
delivery: await api.testSlackDestination({
|
|
23297
|
+
bearerToken: String(input["bearerToken"]),
|
|
23298
|
+
projectId: String(input["projectId"]),
|
|
23299
|
+
destinationId: String(input["destinationId"])
|
|
23300
|
+
})
|
|
23301
|
+
};
|
|
23302
|
+
} catch (error) {
|
|
23303
|
+
mapMcpError12(error);
|
|
23304
|
+
}
|
|
23305
|
+
},
|
|
23306
|
+
async delete_slack_destination(input) {
|
|
23307
|
+
try {
|
|
23308
|
+
return {
|
|
23309
|
+
destination: await api.deleteSlackDestination({
|
|
23310
|
+
bearerToken: String(input["bearerToken"]),
|
|
23311
|
+
projectId: String(input["projectId"]),
|
|
23312
|
+
destinationId: String(input["destinationId"])
|
|
23313
|
+
})
|
|
23314
|
+
};
|
|
23315
|
+
} catch (error) {
|
|
23316
|
+
mapMcpError12(error);
|
|
23317
|
+
}
|
|
23318
|
+
}
|
|
23319
|
+
};
|
|
23320
|
+
}
|
|
23321
|
+
|
|
23322
|
+
// src/token-tools.ts
|
|
23323
|
+
function mapMcpError13(error) {
|
|
22647
23324
|
if (error instanceof TokenManagementApiError) {
|
|
22648
23325
|
throw new Error(`mcp_tool_error:${error.code}`);
|
|
22649
23326
|
}
|
|
@@ -22664,7 +23341,7 @@ function createTokenMcpTools(api) {
|
|
|
22664
23341
|
tokens: await api.listProjectTokens(requestInput)
|
|
22665
23342
|
};
|
|
22666
23343
|
} catch (error) {
|
|
22667
|
-
|
|
23344
|
+
mapMcpError13(error);
|
|
22668
23345
|
}
|
|
22669
23346
|
},
|
|
22670
23347
|
async create_project_token(input) {
|
|
@@ -22677,7 +23354,7 @@ function createTokenMcpTools(api) {
|
|
|
22677
23354
|
})
|
|
22678
23355
|
};
|
|
22679
23356
|
} catch (error) {
|
|
22680
|
-
|
|
23357
|
+
mapMcpError13(error);
|
|
22681
23358
|
}
|
|
22682
23359
|
},
|
|
22683
23360
|
async revoke_project_token(input) {
|
|
@@ -22690,7 +23367,7 @@ function createTokenMcpTools(api) {
|
|
|
22690
23367
|
})
|
|
22691
23368
|
};
|
|
22692
23369
|
} catch (error) {
|
|
22693
|
-
|
|
23370
|
+
mapMcpError13(error);
|
|
22694
23371
|
}
|
|
22695
23372
|
},
|
|
22696
23373
|
async list_member_tokens(input) {
|
|
@@ -22705,7 +23382,7 @@ function createTokenMcpTools(api) {
|
|
|
22705
23382
|
tokens: await api.listMemberTokens(requestInput)
|
|
22706
23383
|
};
|
|
22707
23384
|
} catch (error) {
|
|
22708
|
-
|
|
23385
|
+
mapMcpError13(error);
|
|
22709
23386
|
}
|
|
22710
23387
|
},
|
|
22711
23388
|
async create_member_token(input) {
|
|
@@ -22717,7 +23394,7 @@ function createTokenMcpTools(api) {
|
|
|
22717
23394
|
})
|
|
22718
23395
|
};
|
|
22719
23396
|
} catch (error) {
|
|
22720
|
-
|
|
23397
|
+
mapMcpError13(error);
|
|
22721
23398
|
}
|
|
22722
23399
|
},
|
|
22723
23400
|
async revoke_member_token(input) {
|
|
@@ -22729,14 +23406,14 @@ function createTokenMcpTools(api) {
|
|
|
22729
23406
|
})
|
|
22730
23407
|
};
|
|
22731
23408
|
} catch (error) {
|
|
22732
|
-
|
|
23409
|
+
mapMcpError13(error);
|
|
22733
23410
|
}
|
|
22734
23411
|
}
|
|
22735
23412
|
};
|
|
22736
23413
|
}
|
|
22737
23414
|
|
|
22738
23415
|
// src/webhook-tools.ts
|
|
22739
|
-
function
|
|
23416
|
+
function mapMcpError14(error) {
|
|
22740
23417
|
if (error instanceof WebhookApiError) {
|
|
22741
23418
|
throw new Error(`mcp_tool_error:${error.code}`);
|
|
22742
23419
|
}
|
|
@@ -22757,7 +23434,7 @@ function createWebhookMcpTools(api) {
|
|
|
22757
23434
|
webhooks: await api.listWebhooks(requestInput)
|
|
22758
23435
|
};
|
|
22759
23436
|
} catch (error) {
|
|
22760
|
-
|
|
23437
|
+
mapMcpError14(error);
|
|
22761
23438
|
}
|
|
22762
23439
|
},
|
|
22763
23440
|
async create_webhook(input) {
|
|
@@ -22778,7 +23455,7 @@ function createWebhookMcpTools(api) {
|
|
|
22778
23455
|
webhook: await api.createWebhook(requestInput)
|
|
22779
23456
|
};
|
|
22780
23457
|
} catch (error) {
|
|
22781
|
-
|
|
23458
|
+
mapMcpError14(error);
|
|
22782
23459
|
}
|
|
22783
23460
|
},
|
|
22784
23461
|
async update_webhook(input) {
|
|
@@ -22803,7 +23480,7 @@ function createWebhookMcpTools(api) {
|
|
|
22803
23480
|
webhook: await api.updateWebhook(requestInput)
|
|
22804
23481
|
};
|
|
22805
23482
|
} catch (error) {
|
|
22806
|
-
|
|
23483
|
+
mapMcpError14(error);
|
|
22807
23484
|
}
|
|
22808
23485
|
},
|
|
22809
23486
|
async delete_webhook(input) {
|
|
@@ -22815,7 +23492,7 @@ function createWebhookMcpTools(api) {
|
|
|
22815
23492
|
})
|
|
22816
23493
|
};
|
|
22817
23494
|
} catch (error) {
|
|
22818
|
-
|
|
23495
|
+
mapMcpError14(error);
|
|
22819
23496
|
}
|
|
22820
23497
|
},
|
|
22821
23498
|
async test_webhook(input) {
|
|
@@ -22831,7 +23508,7 @@ function createWebhookMcpTools(api) {
|
|
|
22831
23508
|
delivery: await api.testWebhook(requestInput)
|
|
22832
23509
|
};
|
|
22833
23510
|
} catch (error) {
|
|
22834
|
-
|
|
23511
|
+
mapMcpError14(error);
|
|
22835
23512
|
}
|
|
22836
23513
|
},
|
|
22837
23514
|
async list_webhook_deliveries(input) {
|
|
@@ -22847,7 +23524,7 @@ function createWebhookMcpTools(api) {
|
|
|
22847
23524
|
deliveries: await api.listWebhookDeliveries(requestInput)
|
|
22848
23525
|
};
|
|
22849
23526
|
} catch (error) {
|
|
22850
|
-
|
|
23527
|
+
mapMcpError14(error);
|
|
22851
23528
|
}
|
|
22852
23529
|
},
|
|
22853
23530
|
async retry_webhook_delivery(input) {
|
|
@@ -22858,14 +23535,14 @@ function createWebhookMcpTools(api) {
|
|
|
22858
23535
|
deliveryId: String(input["deliveryId"])
|
|
22859
23536
|
});
|
|
22860
23537
|
} catch (error) {
|
|
22861
|
-
|
|
23538
|
+
mapMcpError14(error);
|
|
22862
23539
|
}
|
|
22863
23540
|
}
|
|
22864
23541
|
};
|
|
22865
23542
|
}
|
|
22866
23543
|
|
|
22867
23544
|
// src/weekly-report-tools.ts
|
|
22868
|
-
function
|
|
23545
|
+
function mapMcpError15(error) {
|
|
22869
23546
|
if (error instanceof WeeklyReportApiError) {
|
|
22870
23547
|
throw new Error(`mcp_tool_error:${error.code}`);
|
|
22871
23548
|
}
|
|
@@ -22883,7 +23560,7 @@ function createWeeklyReportMcpTools(api) {
|
|
|
22883
23560
|
})
|
|
22884
23561
|
};
|
|
22885
23562
|
} catch (error) {
|
|
22886
|
-
|
|
23563
|
+
mapMcpError15(error);
|
|
22887
23564
|
}
|
|
22888
23565
|
},
|
|
22889
23566
|
async create_weekly_report_channel(input) {
|
|
@@ -22899,7 +23576,7 @@ function createWeeklyReportMcpTools(api) {
|
|
|
22899
23576
|
})
|
|
22900
23577
|
};
|
|
22901
23578
|
} catch (error) {
|
|
22902
|
-
|
|
23579
|
+
mapMcpError15(error);
|
|
22903
23580
|
}
|
|
22904
23581
|
},
|
|
22905
23582
|
async update_weekly_report_channel(input) {
|
|
@@ -22914,7 +23591,7 @@ function createWeeklyReportMcpTools(api) {
|
|
|
22914
23591
|
})
|
|
22915
23592
|
};
|
|
22916
23593
|
} catch (error) {
|
|
22917
|
-
|
|
23594
|
+
mapMcpError15(error);
|
|
22918
23595
|
}
|
|
22919
23596
|
},
|
|
22920
23597
|
async delete_weekly_report_channel(input) {
|
|
@@ -22926,7 +23603,7 @@ function createWeeklyReportMcpTools(api) {
|
|
|
22926
23603
|
})
|
|
22927
23604
|
};
|
|
22928
23605
|
} catch (error) {
|
|
22929
|
-
|
|
23606
|
+
mapMcpError15(error);
|
|
22930
23607
|
}
|
|
22931
23608
|
}
|
|
22932
23609
|
};
|
|
@@ -22977,6 +23654,7 @@ async function createDefaultMcpTools(input = {}) {
|
|
|
22977
23654
|
...createServicesMcpTools(retrievalApi),
|
|
22978
23655
|
...createTokenMcpTools(createTokenManagementApi(httpClient)),
|
|
22979
23656
|
...createWebhookMcpTools(createWebhookApi(httpClient)),
|
|
23657
|
+
...createSlackMcpTools(createSlackApi(httpClient)),
|
|
22980
23658
|
...createWeeklyReportMcpTools(createWeeklyReportApi(httpClient)),
|
|
22981
23659
|
...createAlertMcpTools(createAlertApi(httpClient)),
|
|
22982
23660
|
...createProjectMcpTools(createProjectManagementApi(httpClient)),
|
|
@@ -24661,6 +25339,45 @@ var MCP_TOOL_CATALOG = [
|
|
|
24661
25339
|
deliveryId: external_exports.string()
|
|
24662
25340
|
})
|
|
24663
25341
|
},
|
|
25342
|
+
{
|
|
25343
|
+
name: "list_slack_destinations",
|
|
25344
|
+
group: "slack",
|
|
25345
|
+
description: "List reusable connected Slack destinations for a project organization.",
|
|
25346
|
+
inputSchema: external_exports.object({
|
|
25347
|
+
bearerToken: external_exports.string(),
|
|
25348
|
+
projectId: external_exports.string()
|
|
25349
|
+
})
|
|
25350
|
+
},
|
|
25351
|
+
{
|
|
25352
|
+
name: "get_slack_connect_url",
|
|
25353
|
+
group: "slack",
|
|
25354
|
+
description: "Return a browser Slack connect URL for a project.",
|
|
25355
|
+
inputSchema: external_exports.object({
|
|
25356
|
+
bearerToken: external_exports.string(),
|
|
25357
|
+
projectId: external_exports.string(),
|
|
25358
|
+
returnTo: external_exports.string().optional()
|
|
25359
|
+
})
|
|
25360
|
+
},
|
|
25361
|
+
{
|
|
25362
|
+
name: "test_slack_destination",
|
|
25363
|
+
group: "slack",
|
|
25364
|
+
description: "Send a test message to a connected Slack destination.",
|
|
25365
|
+
inputSchema: external_exports.object({
|
|
25366
|
+
bearerToken: external_exports.string(),
|
|
25367
|
+
projectId: external_exports.string(),
|
|
25368
|
+
destinationId: external_exports.string()
|
|
25369
|
+
})
|
|
25370
|
+
},
|
|
25371
|
+
{
|
|
25372
|
+
name: "delete_slack_destination",
|
|
25373
|
+
group: "slack",
|
|
25374
|
+
description: "Delete a connected Slack destination from a project organization.",
|
|
25375
|
+
inputSchema: external_exports.object({
|
|
25376
|
+
bearerToken: external_exports.string(),
|
|
25377
|
+
projectId: external_exports.string(),
|
|
25378
|
+
destinationId: external_exports.string()
|
|
25379
|
+
})
|
|
25380
|
+
},
|
|
24664
25381
|
{
|
|
24665
25382
|
name: "list_weekly_report_channels",
|
|
24666
25383
|
group: "weekly_reports",
|
|
@@ -24726,7 +25443,7 @@ var MCP_TOOL_CATALOG = [
|
|
|
24726
25443
|
channel: external_exports.string(),
|
|
24727
25444
|
conditionType: external_exports.string(),
|
|
24728
25445
|
severityMin: external_exports.string().optional(),
|
|
24729
|
-
config: jsonObjectSchema
|
|
25446
|
+
config: jsonObjectSchema,
|
|
24730
25447
|
isEnabled: external_exports.boolean().optional()
|
|
24731
25448
|
})
|
|
24732
25449
|
},
|
|
@@ -25030,7 +25747,7 @@ function createMcpServer(input) {
|
|
|
25030
25747
|
},
|
|
25031
25748
|
serverInfo: {
|
|
25032
25749
|
name: "@debugbundle/mcp",
|
|
25033
|
-
version: "0.1.
|
|
25750
|
+
version: "0.1.2"
|
|
25034
25751
|
}
|
|
25035
25752
|
}
|
|
25036
25753
|
};
|