@debugbundle/cli 1.1.2 → 1.3.0
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 +367 -50
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -14486,25 +14486,74 @@ var CaptureProbeEventsSchema = external_exports.enum(CaptureProbeEventsValues);
|
|
|
14486
14486
|
var RequestSignalClassificationValues = ["incident_signal", "context_signal"];
|
|
14487
14487
|
var RequestSignalClassificationSchema = external_exports.enum(RequestSignalClassificationValues);
|
|
14488
14488
|
var RECOMMENDED_IMMEDIATE_CLIENT_ERROR_STATUSES = [401, 403, 409, 422];
|
|
14489
|
+
var HTTP_METHOD_VALUES = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"];
|
|
14489
14490
|
var ImmediateClientErrorStatusSchema = external_exports.number().int().min(400).max(499);
|
|
14491
|
+
var HttpMethodSchema = external_exports.enum(HTTP_METHOD_VALUES);
|
|
14490
14492
|
function normalizeImmediateClientErrorStatuses(statuses) {
|
|
14491
14493
|
return Array.from(new Set(statuses)).sort((left, right) => left - right);
|
|
14492
14494
|
}
|
|
14493
14495
|
var ImmediateClientErrorStatusesSchema = external_exports.array(ImmediateClientErrorStatusSchema).max(12).transform((statuses) => normalizeImmediateClientErrorStatuses(statuses));
|
|
14496
|
+
function normalizePathPattern(value) {
|
|
14497
|
+
return value.trim().replace(/\/{2,}/g, "/");
|
|
14498
|
+
}
|
|
14499
|
+
function isValidPathPattern(value) {
|
|
14500
|
+
const normalized = normalizePathPattern(value);
|
|
14501
|
+
if (!normalized.startsWith("/") || normalized.includes("?") || normalized.includes("#")) {
|
|
14502
|
+
return false;
|
|
14503
|
+
}
|
|
14504
|
+
const wildcardIndex = normalized.indexOf("*");
|
|
14505
|
+
return wildcardIndex === -1 || wildcardIndex === normalized.length - 1;
|
|
14506
|
+
}
|
|
14507
|
+
function normalizeHttpMethods(methods) {
|
|
14508
|
+
if (methods === void 0 || methods.length === 0) {
|
|
14509
|
+
return [];
|
|
14510
|
+
}
|
|
14511
|
+
const normalized = methods.map((method) => method.toUpperCase()).filter(
|
|
14512
|
+
(method) => HTTP_METHOD_VALUES.includes(method)
|
|
14513
|
+
);
|
|
14514
|
+
return Array.from(new Set(normalized)).sort();
|
|
14515
|
+
}
|
|
14516
|
+
function normalizeImmediateClientErrorPathRules(rules) {
|
|
14517
|
+
const normalized = rules.map((rule) => ({
|
|
14518
|
+
status_code: rule.status_code,
|
|
14519
|
+
path_pattern: normalizePathPattern(rule.path_pattern),
|
|
14520
|
+
methods: normalizeHttpMethods(rule.methods)
|
|
14521
|
+
}));
|
|
14522
|
+
const deduped = /* @__PURE__ */ new Map();
|
|
14523
|
+
for (const rule of normalized) {
|
|
14524
|
+
deduped.set(`${rule.status_code}:${rule.path_pattern}:${rule.methods.join(",")}`, rule);
|
|
14525
|
+
}
|
|
14526
|
+
return Array.from(deduped.values()).sort((left, right) => {
|
|
14527
|
+
if (left.status_code !== right.status_code) return left.status_code - right.status_code;
|
|
14528
|
+
const pathComparison = left.path_pattern.localeCompare(right.path_pattern);
|
|
14529
|
+
if (pathComparison !== 0) return pathComparison;
|
|
14530
|
+
return left.methods.join(",").localeCompare(right.methods.join(","));
|
|
14531
|
+
});
|
|
14532
|
+
}
|
|
14533
|
+
var ImmediateClientErrorPathRuleSchema = external_exports.object({
|
|
14534
|
+
status_code: ImmediateClientErrorStatusSchema,
|
|
14535
|
+
path_pattern: external_exports.string().min(1).max(256).transform(normalizePathPattern).refine(isValidPathPattern, {
|
|
14536
|
+
message: "path_pattern must start with / and may only use a terminal * wildcard"
|
|
14537
|
+
}),
|
|
14538
|
+
methods: external_exports.array(HttpMethodSchema).max(7).optional().default([]).transform(normalizeHttpMethods)
|
|
14539
|
+
});
|
|
14540
|
+
var ImmediateClientErrorPathRulesSchema = external_exports.array(ImmediateClientErrorPathRuleSchema).max(25).transform((rules) => normalizeImmediateClientErrorPathRules(rules));
|
|
14494
14541
|
var ResolvedCapturePolicySchema = external_exports.object({
|
|
14495
14542
|
preset: CapturePresetSchema,
|
|
14496
14543
|
capture_logs: CaptureLogsSchema,
|
|
14497
14544
|
capture_request_events: CaptureRequestEventsSchema,
|
|
14498
14545
|
capture_breadcrumbs: CaptureBreadcrumbsSchema,
|
|
14499
14546
|
capture_probe_events: CaptureProbeEventsSchema,
|
|
14500
|
-
immediate_client_error_statuses: ImmediateClientErrorStatusesSchema
|
|
14547
|
+
immediate_client_error_statuses: ImmediateClientErrorStatusesSchema,
|
|
14548
|
+
immediate_client_error_path_rules: ImmediateClientErrorPathRulesSchema.default([])
|
|
14501
14549
|
});
|
|
14502
14550
|
var CapturePolicyOverridesSchema = external_exports.object({
|
|
14503
14551
|
capture_logs: CaptureLogsSchema.nullable(),
|
|
14504
14552
|
capture_request_events: CaptureRequestEventsSchema.nullable(),
|
|
14505
14553
|
capture_breadcrumbs: CaptureBreadcrumbsSchema.nullable(),
|
|
14506
14554
|
capture_probe_events: CaptureProbeEventsSchema.nullable(),
|
|
14507
|
-
immediate_client_error_statuses: ImmediateClientErrorStatusesSchema.nullable()
|
|
14555
|
+
immediate_client_error_statuses: ImmediateClientErrorStatusesSchema.nullable(),
|
|
14556
|
+
immediate_client_error_path_rules: ImmediateClientErrorPathRulesSchema.nullable().default(null)
|
|
14508
14557
|
});
|
|
14509
14558
|
var CapturePolicyResponseSchema = external_exports.object({
|
|
14510
14559
|
access_mode: external_exports.enum(["manage", "preview"]),
|
|
@@ -14519,6 +14568,7 @@ var CapturePolicySchema = external_exports.object({
|
|
|
14519
14568
|
capture_breadcrumbs: CaptureBreadcrumbsSchema.nullable(),
|
|
14520
14569
|
capture_probe_events: CaptureProbeEventsSchema.nullable(),
|
|
14521
14570
|
immediate_client_error_statuses: ImmediateClientErrorStatusesSchema.nullable(),
|
|
14571
|
+
immediate_client_error_path_rules: ImmediateClientErrorPathRulesSchema.nullable().default(null),
|
|
14522
14572
|
updated_at: external_exports.string().datetime()
|
|
14523
14573
|
});
|
|
14524
14574
|
var CapturePolicyUpdateSchema = external_exports.object({
|
|
@@ -14527,7 +14577,8 @@ var CapturePolicyUpdateSchema = external_exports.object({
|
|
|
14527
14577
|
capture_request_events: CaptureRequestEventsSchema.nullable().optional(),
|
|
14528
14578
|
capture_breadcrumbs: CaptureBreadcrumbsSchema.nullable().optional(),
|
|
14529
14579
|
capture_probe_events: CaptureProbeEventsSchema.nullable().optional(),
|
|
14530
|
-
immediate_client_error_statuses: ImmediateClientErrorStatusesSchema.nullable().optional()
|
|
14580
|
+
immediate_client_error_statuses: ImmediateClientErrorStatusesSchema.nullable().optional(),
|
|
14581
|
+
immediate_client_error_path_rules: ImmediateClientErrorPathRulesSchema.nullable().optional()
|
|
14531
14582
|
});
|
|
14532
14583
|
var PRESET_DEFAULTS = {
|
|
14533
14584
|
minimal: {
|
|
@@ -14535,30 +14586,69 @@ var PRESET_DEFAULTS = {
|
|
|
14535
14586
|
capture_request_events: "failures_only",
|
|
14536
14587
|
capture_breadcrumbs: "local_only",
|
|
14537
14588
|
capture_probe_events: "buffer_only",
|
|
14538
|
-
immediate_client_error_statuses: []
|
|
14589
|
+
immediate_client_error_statuses: [],
|
|
14590
|
+
immediate_client_error_path_rules: []
|
|
14539
14591
|
},
|
|
14540
14592
|
balanced: {
|
|
14541
14593
|
capture_logs: "warning",
|
|
14542
14594
|
capture_request_events: "failures_only",
|
|
14543
14595
|
capture_breadcrumbs: "exception_only",
|
|
14544
14596
|
capture_probe_events: "buffer_only",
|
|
14545
|
-
immediate_client_error_statuses: []
|
|
14597
|
+
immediate_client_error_statuses: [],
|
|
14598
|
+
immediate_client_error_path_rules: []
|
|
14546
14599
|
},
|
|
14547
14600
|
investigative: {
|
|
14548
14601
|
capture_logs: "info",
|
|
14549
14602
|
capture_request_events: "all",
|
|
14550
14603
|
capture_breadcrumbs: "standalone",
|
|
14551
14604
|
capture_probe_events: "standalone_when_activated",
|
|
14552
|
-
immediate_client_error_statuses: [...RECOMMENDED_IMMEDIATE_CLIENT_ERROR_STATUSES]
|
|
14605
|
+
immediate_client_error_statuses: [...RECOMMENDED_IMMEDIATE_CLIENT_ERROR_STATUSES],
|
|
14606
|
+
immediate_client_error_path_rules: []
|
|
14553
14607
|
}
|
|
14554
14608
|
};
|
|
14555
14609
|
var BALANCED_IMMEDIATE_REQUEST_STATUSES = /* @__PURE__ */ new Set([408, 423, 424, 425, 429]);
|
|
14556
14610
|
var INVESTIGATIVE_IMMEDIATE_REQUEST_STATUSES = /* @__PURE__ */ new Set([...BALANCED_IMMEDIATE_REQUEST_STATUSES, 409]);
|
|
14557
|
-
|
|
14558
|
-
|
|
14559
|
-
|
|
14611
|
+
function normalizeRequestPath(value) {
|
|
14612
|
+
if (typeof value !== "string") {
|
|
14613
|
+
return null;
|
|
14614
|
+
}
|
|
14615
|
+
const trimmed = value.trim();
|
|
14616
|
+
if (trimmed.length === 0) {
|
|
14617
|
+
return null;
|
|
14618
|
+
}
|
|
14619
|
+
const path = trimmed.startsWith("http://") || trimmed.startsWith("https://") ? (() => {
|
|
14620
|
+
try {
|
|
14621
|
+
return new URL(trimmed).pathname;
|
|
14622
|
+
} catch {
|
|
14623
|
+
return trimmed;
|
|
14624
|
+
}
|
|
14625
|
+
})() : trimmed;
|
|
14626
|
+
return (path.split(/[?#]/, 1)[0] ?? path).replace(/\/{2,}/g, "/");
|
|
14627
|
+
}
|
|
14628
|
+
function pathPatternMatches(rulePattern, requestPath) {
|
|
14629
|
+
const pattern = normalizePathPattern(rulePattern);
|
|
14630
|
+
if (!pattern.endsWith("*")) {
|
|
14631
|
+
return requestPath === pattern;
|
|
14632
|
+
}
|
|
14633
|
+
const prefix = pattern.slice(0, -1);
|
|
14634
|
+
return requestPath.startsWith(prefix);
|
|
14635
|
+
}
|
|
14636
|
+
function matchesImmediateClientErrorPathRule(input2) {
|
|
14637
|
+
const { responseStatus, immediateClientErrorPathRules = [] } = input2;
|
|
14638
|
+
if (responseStatus === null || !Number.isFinite(responseStatus) || immediateClientErrorPathRules.length === 0) {
|
|
14639
|
+
return false;
|
|
14640
|
+
}
|
|
14641
|
+
const requestPath = normalizeRequestPath(input2.requestPath);
|
|
14642
|
+
if (requestPath === null) {
|
|
14643
|
+
return false;
|
|
14644
|
+
}
|
|
14645
|
+
const httpMethod = typeof input2.httpMethod === "string" ? input2.httpMethod.toUpperCase() : null;
|
|
14646
|
+
return immediateClientErrorPathRules.some(
|
|
14647
|
+
(rule) => rule.status_code === responseStatus && (rule.methods.length === 0 || httpMethod !== null && rule.methods.includes(httpMethod)) && pathPatternMatches(rule.path_pattern, requestPath)
|
|
14648
|
+
);
|
|
14649
|
+
}
|
|
14560
14650
|
function classifyRequestStatus(input2) {
|
|
14561
|
-
const { responseStatus, capturePreset, immediateClientErrorStatuses = [] } = input2;
|
|
14651
|
+
const { responseStatus, capturePreset, immediateClientErrorStatuses = [], immediateClientErrorPathRules = [] } = input2;
|
|
14562
14652
|
if (responseStatus === null || !Number.isFinite(responseStatus)) {
|
|
14563
14653
|
return "context_signal";
|
|
14564
14654
|
}
|
|
@@ -14568,6 +14658,14 @@ function classifyRequestStatus(input2) {
|
|
|
14568
14658
|
if (immediateClientErrorStatuses.includes(responseStatus)) {
|
|
14569
14659
|
return "incident_signal";
|
|
14570
14660
|
}
|
|
14661
|
+
if (matchesImmediateClientErrorPathRule({
|
|
14662
|
+
responseStatus,
|
|
14663
|
+
requestPath: input2.requestPath,
|
|
14664
|
+
httpMethod: input2.httpMethod,
|
|
14665
|
+
immediateClientErrorPathRules
|
|
14666
|
+
})) {
|
|
14667
|
+
return "incident_signal";
|
|
14668
|
+
}
|
|
14571
14669
|
if (capturePreset === "investigative") {
|
|
14572
14670
|
return INVESTIGATIVE_IMMEDIATE_REQUEST_STATUSES.has(responseStatus) ? "incident_signal" : "context_signal";
|
|
14573
14671
|
}
|
|
@@ -14577,31 +14675,10 @@ function classifyRequestStatus(input2) {
|
|
|
14577
14675
|
return "context_signal";
|
|
14578
14676
|
}
|
|
14579
14677
|
function getRequestAnomalyThreshold(input2) {
|
|
14580
|
-
const { responseStatus
|
|
14678
|
+
const { responseStatus } = input2;
|
|
14581
14679
|
if (responseStatus === null || !Number.isFinite(responseStatus) || responseStatus < 400 || responseStatus >= 500) {
|
|
14582
14680
|
return null;
|
|
14583
14681
|
}
|
|
14584
|
-
if (capturePreset === "minimal") {
|
|
14585
|
-
return null;
|
|
14586
|
-
}
|
|
14587
|
-
if (capturePreset === "investigative") {
|
|
14588
|
-
return INVESTIGATIVE_ANOMALY_STATUSES.has(responseStatus) ? {
|
|
14589
|
-
minimum_occurrences_5m: 8,
|
|
14590
|
-
minimum_ratio_5m_to_1h: 2
|
|
14591
|
-
} : null;
|
|
14592
|
-
}
|
|
14593
|
-
if (BALANCED_STANDARD_ANOMALY_STATUSES.has(responseStatus)) {
|
|
14594
|
-
return {
|
|
14595
|
-
minimum_occurrences_5m: 20,
|
|
14596
|
-
minimum_ratio_5m_to_1h: 3
|
|
14597
|
-
};
|
|
14598
|
-
}
|
|
14599
|
-
if (BALANCED_HIGH_VOLUME_ANOMALY_STATUSES.has(responseStatus)) {
|
|
14600
|
-
return {
|
|
14601
|
-
minimum_occurrences_5m: 50,
|
|
14602
|
-
minimum_ratio_5m_to_1h: 5
|
|
14603
|
-
};
|
|
14604
|
-
}
|
|
14605
14682
|
return null;
|
|
14606
14683
|
}
|
|
14607
14684
|
|
|
@@ -14694,7 +14771,7 @@ function isIpLikeHost(value) {
|
|
|
14694
14771
|
return /^(?:\d{1,3}\.){3}\d{1,3}$/.test(host) || /^\[[0-9a-f:]+\]$/i.test(host) || host.includes(":") && /^[0-9a-f:]+$/i.test(host);
|
|
14695
14772
|
}
|
|
14696
14773
|
|
|
14697
|
-
// ../../packages/shared-types/src/capture-
|
|
14774
|
+
// ../../packages/shared-types/src/capture-rule-schemas.ts
|
|
14698
14775
|
var CAPTURE_RULE_EVENT_TYPES = [
|
|
14699
14776
|
"backend_exception",
|
|
14700
14777
|
"request_event",
|
|
@@ -14722,6 +14799,7 @@ var CaptureRuleSampleEventClassSchema = external_exports.enum(CaptureRuleSampleE
|
|
|
14722
14799
|
var CaptureRuleRuntimeSchema = external_exports.enum(CAPTURE_RULE_RUNTIME_VALUES);
|
|
14723
14800
|
var CaptureRuleEventTypeSchema = external_exports.enum(CAPTURE_RULE_EVENT_TYPES);
|
|
14724
14801
|
var BrowserEventKindSchema = external_exports.enum(["window_error", "resource_error"]);
|
|
14802
|
+
var CaptureRuleClientKindSchema = external_exports.enum(["human", "bot", "unknown"]);
|
|
14725
14803
|
function normalizeOptionalTrimmedString(value) {
|
|
14726
14804
|
const trimmed = value?.trim();
|
|
14727
14805
|
return trimmed && trimmed.length > 0 ? trimmed : void 0;
|
|
@@ -14799,6 +14877,9 @@ var CaptureRuleMatcherSchema = external_exports.object({
|
|
|
14799
14877
|
message_contains: external_exports.string().min(1).max(500).optional(),
|
|
14800
14878
|
message_equals: external_exports.string().min(1).max(500).optional(),
|
|
14801
14879
|
browser_event_kind: BrowserEventKindSchema.optional(),
|
|
14880
|
+
browser_event_opaque: external_exports.boolean().optional(),
|
|
14881
|
+
client_kind: CaptureRuleClientKindSchema.optional(),
|
|
14882
|
+
bot_family: external_exports.string().min(1).max(120).optional(),
|
|
14802
14883
|
resource_url: UrlMatcherSchema.optional(),
|
|
14803
14884
|
request_url: UrlMatcherSchema.optional(),
|
|
14804
14885
|
status_codes: external_exports.array(external_exports.number().int().min(100).max(599)).min(1).optional(),
|
|
@@ -14813,6 +14894,7 @@ var CaptureRuleMatcherSchema = external_exports.object({
|
|
|
14813
14894
|
const errorName = normalizeOptionalTrimmedString(value.error_name);
|
|
14814
14895
|
const messageContains = normalizeOptionalTrimmedString(value.message_contains);
|
|
14815
14896
|
const messageEquals = normalizeOptionalTrimmedString(value.message_equals);
|
|
14897
|
+
const botFamily = normalizeOptionalTrimmedString(value.bot_family);
|
|
14816
14898
|
const statusCodes = normalizeNumberArray(value.status_codes);
|
|
14817
14899
|
if (eventTypes !== void 0) {
|
|
14818
14900
|
normalized.event_types = eventTypes;
|
|
@@ -14841,6 +14923,15 @@ var CaptureRuleMatcherSchema = external_exports.object({
|
|
|
14841
14923
|
if (value.browser_event_kind !== void 0) {
|
|
14842
14924
|
normalized.browser_event_kind = value.browser_event_kind;
|
|
14843
14925
|
}
|
|
14926
|
+
if (value.browser_event_opaque !== void 0) {
|
|
14927
|
+
normalized.browser_event_opaque = value.browser_event_opaque;
|
|
14928
|
+
}
|
|
14929
|
+
if (value.client_kind !== void 0) {
|
|
14930
|
+
normalized.client_kind = value.client_kind;
|
|
14931
|
+
}
|
|
14932
|
+
if (botFamily !== void 0) {
|
|
14933
|
+
normalized.bot_family = botFamily;
|
|
14934
|
+
}
|
|
14844
14935
|
if (value.resource_url !== void 0) {
|
|
14845
14936
|
normalized.resource_url = value.resource_url;
|
|
14846
14937
|
}
|
|
@@ -14867,6 +14958,9 @@ var CaptureRuleMatcherSchema = external_exports.object({
|
|
|
14867
14958
|
"message_contains",
|
|
14868
14959
|
"message_equals",
|
|
14869
14960
|
"browser_event_kind",
|
|
14961
|
+
"browser_event_opaque",
|
|
14962
|
+
"client_kind",
|
|
14963
|
+
"bot_family",
|
|
14870
14964
|
"resource_url",
|
|
14871
14965
|
"request_url",
|
|
14872
14966
|
"status_codes",
|
|
@@ -15049,6 +15143,8 @@ var CaptureRulesFileSchema = external_exports.object({
|
|
|
15049
15143
|
version: external_exports.literal(1),
|
|
15050
15144
|
rules: external_exports.array(CaptureRuleSchema)
|
|
15051
15145
|
});
|
|
15146
|
+
|
|
15147
|
+
// ../../packages/shared-types/src/capture-rule-evaluation.ts
|
|
15052
15148
|
var CaptureRuleEvaluationUrlSchema = external_exports.object({
|
|
15053
15149
|
host: external_exports.string().min(1).transform((value) => value.toLowerCase()).optional(),
|
|
15054
15150
|
path: external_exports.string().min(1).transform((value) => value.startsWith("/") ? value : `/${value}`)
|
|
@@ -15064,11 +15160,40 @@ var CaptureRuleEvaluationContextSchema = external_exports.object({
|
|
|
15064
15160
|
error_name: external_exports.string().min(1).optional(),
|
|
15065
15161
|
message: external_exports.string().min(1).optional(),
|
|
15066
15162
|
browser_event_kind: BrowserEventKindSchema.optional(),
|
|
15163
|
+
browser_event_opaque: external_exports.boolean().optional(),
|
|
15164
|
+
client_kind: CaptureRuleClientKindSchema.optional(),
|
|
15165
|
+
bot_family: external_exports.string().min(1).max(120).optional(),
|
|
15067
15166
|
resource_url: CaptureRuleEvaluationUrlSchema.optional(),
|
|
15068
15167
|
request_url: CaptureRuleEvaluationUrlSchema.optional(),
|
|
15069
15168
|
status_code: external_exports.number().int().min(0).max(599).optional(),
|
|
15070
15169
|
fingerprint: CaptureRuleFingerprintSchema.optional()
|
|
15071
15170
|
});
|
|
15171
|
+
function classifyCaptureRuleClientFromUserAgent(userAgent) {
|
|
15172
|
+
if (userAgent === null || userAgent === void 0) {
|
|
15173
|
+
return { client_kind: "unknown" };
|
|
15174
|
+
}
|
|
15175
|
+
const lower = userAgent.toLowerCase();
|
|
15176
|
+
const knownBots = [
|
|
15177
|
+
{ family: "Googlebot", markers: ["googlebot", "adsbot-google", "google-inspectiontool"] },
|
|
15178
|
+
{ family: "Bingbot", markers: ["bingbot", "msnbot"] },
|
|
15179
|
+
{ family: "DuckDuckBot", markers: ["duckduckbot"] },
|
|
15180
|
+
{ family: "Applebot", markers: ["applebot"] },
|
|
15181
|
+
{ family: "YandexBot", markers: ["yandexbot"] },
|
|
15182
|
+
{ family: "Baiduspider", markers: ["baiduspider"] },
|
|
15183
|
+
{ family: "FacebookBot", markers: ["facebookexternalhit", "facebot"] },
|
|
15184
|
+
{ family: "LinkedInBot", markers: ["linkedinbot"] },
|
|
15185
|
+
{ family: "TwitterBot", markers: ["twitterbot"] },
|
|
15186
|
+
{ family: "Slackbot", markers: ["slackbot"] }
|
|
15187
|
+
];
|
|
15188
|
+
const knownBot = knownBots.find((entry) => entry.markers.some((marker) => lower.includes(marker)));
|
|
15189
|
+
if (knownBot !== void 0) {
|
|
15190
|
+
return { client_kind: "bot", bot_family: knownBot.family };
|
|
15191
|
+
}
|
|
15192
|
+
if (["bot", "crawler", "spider", "slurp"].some((marker) => lower.includes(marker))) {
|
|
15193
|
+
return { client_kind: "bot", bot_family: "OtherBot" };
|
|
15194
|
+
}
|
|
15195
|
+
return { client_kind: "human" };
|
|
15196
|
+
}
|
|
15072
15197
|
|
|
15073
15198
|
// ../../packages/shared-types/src/capture-rule-suggestions.ts
|
|
15074
15199
|
var CaptureRuleSuggestionConfidenceSchema = external_exports.enum(["high", "medium", "low"]);
|
|
@@ -15278,6 +15403,12 @@ var BrowserExceptionEventSchema = external_exports.object({
|
|
|
15278
15403
|
}).strict().optional(),
|
|
15279
15404
|
opaque: external_exports.boolean()
|
|
15280
15405
|
}).strict();
|
|
15406
|
+
var FrontendRejectionReasonSchema = external_exports.object({
|
|
15407
|
+
kind: external_exports.enum(["error", "string", "object", "null", "undefined", "unknown"]),
|
|
15408
|
+
name: external_exports.string().min(1).optional(),
|
|
15409
|
+
message: external_exports.string().min(1).optional(),
|
|
15410
|
+
preview: external_exports.string().min(1).optional()
|
|
15411
|
+
}).strict();
|
|
15281
15412
|
var FrontendExceptionPayloadSchema = external_exports.object({
|
|
15282
15413
|
name: external_exports.string().min(1),
|
|
15283
15414
|
message: external_exports.string().min(1),
|
|
@@ -15290,6 +15421,7 @@ var FrontendExceptionPayloadSchema = external_exports.object({
|
|
|
15290
15421
|
breadcrumbs: external_exports.array(FrontendExceptionBreadcrumbSchema).optional(),
|
|
15291
15422
|
device: DeviceInfoSchema.nullable().optional(),
|
|
15292
15423
|
browser_event: BrowserExceptionEventSchema.optional(),
|
|
15424
|
+
rejection_reason: FrontendRejectionReasonSchema.optional(),
|
|
15293
15425
|
dom_context: external_exports.object({
|
|
15294
15426
|
mode: external_exports.literal("lightweight"),
|
|
15295
15427
|
html_excerpt: external_exports.string().min(1)
|
|
@@ -15741,7 +15873,7 @@ function buildSkill() {
|
|
|
15741
15873
|
"2. Inspect the incident bundle and reproduction artifact before proposing a fix.",
|
|
15742
15874
|
"3. Run `debugbundle analyze --type improvement --local` after local processing when you need a deterministic change plan.",
|
|
15743
15875
|
"4. Apply the narrowest fix, then validate it with the repository test workflow from `.debugbundle/profile.json`.",
|
|
15744
|
-
"5. When the fix is confirmed, or when the incident was intentionally generated for smoke, verification, or dogfooding, resolve it with `debugbundle resolve <incident-id
|
|
15876
|
+
"5. When the fix is confirmed, or when the incident was intentionally generated for smoke, verification, or dogfooding, resolve it with `debugbundle resolve <incident-id> [incident-id ...]` or MCP `resolve_incident` / `resolve_incidents` so the open queue stays actionable.",
|
|
15745
15877
|
"",
|
|
15746
15878
|
"## Incident Hygiene",
|
|
15747
15879
|
"",
|
|
@@ -15750,6 +15882,15 @@ function buildSkill() {
|
|
|
15750
15882
|
"- Reopen or leave open if the failure is still present, the validation is incomplete, or the incident represents a live unresolved problem.",
|
|
15751
15883
|
"- If a resolved incident regresses, let the platform move it back to `regressed` through normal incident lifecycle behavior.",
|
|
15752
15884
|
"",
|
|
15885
|
+
"## Noise Management",
|
|
15886
|
+
"",
|
|
15887
|
+
"When incident evidence shows repeated low-value operational noise rather than a product bug, evaluate whether a scoped capture rule or capture-policy path rule should handle future matches.",
|
|
15888
|
+
"",
|
|
15889
|
+
"- Run `debugbundle capture-rule suggest <incident-id> --json` before creating a manual rule. Apply deterministic suggestions with `debugbundle capture-rule create-from-suggestion <incident-id> --suggestion-id <id>` after confirming the scope is safe.",
|
|
15890
|
+
"- Prefer project capture rules for operational noise because they are centralized, auditable, and enforced by ingestion and processing. Use SDK `beforeSend` only for app-owned local policy such as final redaction or events that must never leave the runtime.",
|
|
15891
|
+
"- Scope frontend noise by structured evidence such as service, environment, `browser_event_kind`, `browser_event_opaque`, `client_kind`, `bot_family`, and message fields. Do not broadly demote generic `Unhandled promise rejection` incidents without bot-scoped or otherwise narrow evidence.",
|
|
15892
|
+
"- For expected or intentionally promoted 4xx responses on known routes, use capture-policy client-error path rules instead of promoting all client errors: `debugbundle capture-policy set --client-error-path-rule <status=/path/*@GET>`.",
|
|
15893
|
+
"",
|
|
15753
15894
|
"## Profile Validation",
|
|
15754
15895
|
"",
|
|
15755
15896
|
"Use this task after setup or whenever architecture changes make the static profile stale.",
|
|
@@ -15812,10 +15953,21 @@ function buildCliReference() {
|
|
|
15812
15953
|
"- `debugbundle explain <incident-id> [--source <local|cloud>] [--json]`",
|
|
15813
15954
|
"- `debugbundle bundle <incident-id> [--source <local|cloud>] [--json]`",
|
|
15814
15955
|
"- `debugbundle reproduce <incident-id> [--source <local|cloud>] [--json]`",
|
|
15815
|
-
"- `debugbundle resolve <incident-id> [--source <local|cloud>] [--json]`",
|
|
15816
|
-
"- `debugbundle reopen <incident-id> [--source <local|cloud>] [--json]`",
|
|
15956
|
+
"- `debugbundle resolve <incident-id> [incident-id ...] [--source <local|cloud>] [--json]`",
|
|
15957
|
+
"- `debugbundle reopen <incident-id> [incident-id ...] [--source <local|cloud>] [--json]`",
|
|
15817
15958
|
"- `debugbundle analyze --type improvement --local`",
|
|
15818
15959
|
"",
|
|
15960
|
+
"## Noise Management",
|
|
15961
|
+
"",
|
|
15962
|
+
"- `debugbundle capture-rule suggest <incident-id> [--auth-file <path>] [--json]`",
|
|
15963
|
+
"- `debugbundle capture-rule create-from-suggestion <incident-id> --suggestion-id <id> [--name <name>] [--expires-at <ISO8601>] [--auth-file <path>] [--json]`",
|
|
15964
|
+
"- `debugbundle capture-rule list --project-id <id> [--auth-file <path>] [--json]`",
|
|
15965
|
+
"- `debugbundle capture-rule create --project-id <id> --name <name> --action <demote|sample|drop> --matcher-json <json> [--auth-file <path>] [--json]`",
|
|
15966
|
+
"- `debugbundle capture-policy get [--project <id>] [--json]`",
|
|
15967
|
+
"- `debugbundle capture-policy set [--project <id>] --client-error-path-rule <404=/path/*@GET,POST> [--json]`",
|
|
15968
|
+
"",
|
|
15969
|
+
"Use capture-rule suggestions for repeated operational noise after inspecting an incident bundle. Use capture-policy client-error path rules for route-scoped 4xx incidents instead of promoting all client errors.",
|
|
15970
|
+
"",
|
|
15819
15971
|
"## Operational Paths",
|
|
15820
15972
|
"",
|
|
15821
15973
|
"- `.debugbundle/profile.json` \u2014 committed project map and agent validation state",
|
|
@@ -15846,7 +15998,7 @@ function buildCliReference() {
|
|
|
15846
15998
|
"```bash",
|
|
15847
15999
|
"debugbundle incidents --status open --json \\",
|
|
15848
16000
|
` | jq -r '.incidents[] | select(.title | test("smoke test|dogfood|verification|synthetic"; "i")) | .incident_id' \\`,
|
|
15849
|
-
" | xargs
|
|
16001
|
+
" | xargs debugbundle resolve",
|
|
15850
16002
|
"```",
|
|
15851
16003
|
""
|
|
15852
16004
|
].join("\n");
|
|
@@ -15865,19 +16017,28 @@ function buildMcpReference() {
|
|
|
15865
16017
|
"- `get_incident_context` \u2014 fetch deterministic explanation context for triage.",
|
|
15866
16018
|
"- `get_bundle` \u2014 fetch the full debug bundle before proposing a fix.",
|
|
15867
16019
|
"- `get_reproduction` \u2014 fetch reproduction guidance before editing code.",
|
|
15868
|
-
"- `resolve_incident` / `reopen_incident` \u2014 update lifecycle state after validation.",
|
|
16020
|
+
"- `resolve_incident` / `resolve_incidents` / `reopen_incident` / `reopen_incidents` \u2014 update lifecycle state after validation.",
|
|
15869
16021
|
"- `analyze` \u2014 run local agent-oriented analysis from local bundles and skill schemas.",
|
|
15870
16022
|
"",
|
|
15871
16023
|
"- Prefer bundle retrieval tools before reading raw repository files.",
|
|
15872
16024
|
"- Use MCP bundle access when the current issue originated in production.",
|
|
15873
|
-
"- Resolve fixed or intentionally generated incidents with `resolve_incident` so open incidents stay actionable.",
|
|
16025
|
+
"- Resolve fixed or intentionally generated incidents with `resolve_incident` or `resolve_incidents` so open incidents stay actionable.",
|
|
15874
16026
|
"- Fall back to local CLI processing when the project is local-only.",
|
|
15875
16027
|
"",
|
|
16028
|
+
"## Noise and Capture Policy Tools",
|
|
16029
|
+
"",
|
|
16030
|
+
"- `suggest_capture_rules_from_incident` \u2014 generate deterministic capture-rule suggestions from an incident bundle.",
|
|
16031
|
+
"- `create_capture_rule_from_incident_suggestion` \u2014 apply a confirmed suggestion.",
|
|
16032
|
+
"- `list_capture_rules`, `create_capture_rule`, `update_capture_rule`, `delete_capture_rule` \u2014 manage project capture rules.",
|
|
16033
|
+
"- `get_capture_policy`, `update_capture_policy` \u2014 review or update capture policy, including path-scoped client-error incident rules.",
|
|
16034
|
+
"",
|
|
16035
|
+
"Use these tools for repeated low-value operational noise only after inspecting incident evidence. Keep frontend suppression scoped by structured browser and client signals, and use path-scoped capture policy for known 4xx routes.",
|
|
16036
|
+
"",
|
|
15876
16037
|
"## Smoke-Test Cleanup Recipe",
|
|
15877
16038
|
"",
|
|
15878
16039
|
'1. Call `list_incidents` with `status: "open"`.',
|
|
15879
16040
|
"2. Filter incidents whose titles show they were intentionally generated for smoke, dogfood, verification, or synthetic checks.",
|
|
15880
|
-
"3. Call `
|
|
16041
|
+
"3. Call `resolve_incidents` for verified synthetic incidents, or `resolve_incident` for a single incident.",
|
|
15881
16042
|
"4. Call `list_incidents` again and confirm the open queue only contains actionable failures.",
|
|
15882
16043
|
""
|
|
15883
16044
|
].join("\n");
|
|
@@ -15997,6 +16158,16 @@ function buildSkillEvals() {
|
|
|
15997
16158
|
"Leave unresolved incidents open when the failure is still live or unverified."
|
|
15998
16159
|
]
|
|
15999
16160
|
},
|
|
16161
|
+
{
|
|
16162
|
+
name: "noise_management_guidance",
|
|
16163
|
+
prompt: "The same low-value frontend incident keeps reopening. Confirm the skill tells the agent how to evaluate operational noise without hiding real bugs.",
|
|
16164
|
+
expected_behavior: [
|
|
16165
|
+
"Inspect incident evidence before creating a rule.",
|
|
16166
|
+
"Use capture-rule suggestions for repeated operational noise.",
|
|
16167
|
+
"Keep generic frontend suppression narrow with structured browser or bot signals.",
|
|
16168
|
+
"Use capture-policy path rules for known route-scoped 4xx incidents."
|
|
16169
|
+
]
|
|
16170
|
+
},
|
|
16000
16171
|
{
|
|
16001
16172
|
name: "artifact_path_discovery",
|
|
16002
16173
|
prompt: "The user reports an unknown local runtime error. Confirm the skill tells the agent which DebugBundle paths and commands to inspect first.",
|
|
@@ -17011,6 +17182,33 @@ function buildRedactionRecord(bundleBody) {
|
|
|
17011
17182
|
notes: readString(redaction["notes"])
|
|
17012
17183
|
};
|
|
17013
17184
|
}
|
|
17185
|
+
function buildBrowserSignalRecord(bundleBody) {
|
|
17186
|
+
const bundle = isRecord2(bundleBody) ? bundleBody : {};
|
|
17187
|
+
const context = isRecord2(bundle["context"]) ? bundle["context"] : {};
|
|
17188
|
+
const frontend = isRecord2(context["frontend"]) ? context["frontend"] : {};
|
|
17189
|
+
const exceptions = Array.isArray(frontend["exceptions"]) ? frontend["exceptions"] : [];
|
|
17190
|
+
let exception;
|
|
17191
|
+
for (let index = exceptions.length - 1; index >= 0; index -= 1) {
|
|
17192
|
+
const candidate = exceptions[index];
|
|
17193
|
+
if (isRecord2(candidate) && isRecord2(candidate["browser_event"])) {
|
|
17194
|
+
exception = candidate;
|
|
17195
|
+
break;
|
|
17196
|
+
}
|
|
17197
|
+
}
|
|
17198
|
+
const browserEvent = isRecord2(exception) && isRecord2(exception["browser_event"]) ? exception["browser_event"] : null;
|
|
17199
|
+
const device = isRecord2(context["device"]) ? context["device"] : {};
|
|
17200
|
+
const client = classifyCaptureRuleClientFromUserAgent(readString(device["user_agent"]) ?? void 0);
|
|
17201
|
+
if (browserEvent === null && client.client_kind === "unknown") {
|
|
17202
|
+
return null;
|
|
17203
|
+
}
|
|
17204
|
+
return {
|
|
17205
|
+
browser_event_kind: readString(browserEvent?.["kind"]),
|
|
17206
|
+
browser_event_opaque: readBoolean(browserEvent?.["opaque"]),
|
|
17207
|
+
browser_event_message: readString(browserEvent?.["message"]),
|
|
17208
|
+
client_kind: client.client_kind,
|
|
17209
|
+
bot_family: client.bot_family ?? null
|
|
17210
|
+
};
|
|
17211
|
+
}
|
|
17014
17212
|
function buildVisibilityRecord(input2) {
|
|
17015
17213
|
const routeTarget = input2.primarySignal.route_template ?? input2.primarySignal.request_path;
|
|
17016
17214
|
const matchedFields = input2.incident.matched_fields.length === 0 ? "none" : input2.incident.matched_fields.join(", ");
|
|
@@ -17048,6 +17246,14 @@ function buildSuggestedNextChecks(input2) {
|
|
|
17048
17246
|
if (input2.deploy.regression_window === true || input2.incident.status === "regressed") {
|
|
17049
17247
|
suggestions.push("Compare this incident against the most recent deploy and recent regressions.");
|
|
17050
17248
|
}
|
|
17249
|
+
if (input2.browserSignal?.browser_event_opaque === true) {
|
|
17250
|
+
suggestions.push("Treat the browser event as opaque; inspect CSP, cross-origin scripts, resource loading, and framework error boundaries before changing application code.");
|
|
17251
|
+
}
|
|
17252
|
+
if (input2.browserSignal?.client_kind === "bot") {
|
|
17253
|
+
suggestions.push(
|
|
17254
|
+
`Review whether ${input2.browserSignal.bot_family ?? "bot"} traffic is operational noise before applying a bot-scoped capture rule.`
|
|
17255
|
+
);
|
|
17256
|
+
}
|
|
17051
17257
|
if (input2.reproduction.status === "pending") {
|
|
17052
17258
|
suggestions.push("Recheck reproduction guidance after the reproduction artifact is ready.");
|
|
17053
17259
|
}
|
|
@@ -17068,6 +17274,7 @@ function buildIncidentContextRecord(input2) {
|
|
|
17068
17274
|
primarySignal
|
|
17069
17275
|
});
|
|
17070
17276
|
const redaction = buildRedactionRecord(bundleBody);
|
|
17277
|
+
const browserSignal = buildBrowserSignalRecord(bundleBody);
|
|
17071
17278
|
return {
|
|
17072
17279
|
incident: input2.incident,
|
|
17073
17280
|
incident_reason: incidentReason,
|
|
@@ -17083,13 +17290,15 @@ function buildIncidentContextRecord(input2) {
|
|
|
17083
17290
|
},
|
|
17084
17291
|
visibility,
|
|
17085
17292
|
redaction,
|
|
17293
|
+
browser_signal: browserSignal,
|
|
17086
17294
|
suggested_next_checks: buildSuggestedNextChecks({
|
|
17087
17295
|
incident: input2.incident,
|
|
17088
17296
|
bundle: input2.bundle,
|
|
17089
17297
|
reproduction: input2.reproduction,
|
|
17090
17298
|
logs,
|
|
17091
17299
|
primarySignal,
|
|
17092
|
-
deploy
|
|
17300
|
+
deploy,
|
|
17301
|
+
browserSignal
|
|
17093
17302
|
})
|
|
17094
17303
|
};
|
|
17095
17304
|
}
|
|
@@ -17631,7 +17840,7 @@ function getRequestResponseStatus(payload) {
|
|
|
17631
17840
|
const status = payload?.["response_status"];
|
|
17632
17841
|
return typeof status === "number" && Number.isFinite(status) ? status : null;
|
|
17633
17842
|
}
|
|
17634
|
-
function classifyEvent(eventType, logLevel, probeActivationId, payload, capturePreset = "minimal", immediateClientErrorStatuses = []) {
|
|
17843
|
+
function classifyEvent(eventType, logLevel, probeActivationId, payload, capturePreset = "minimal", immediateClientErrorStatuses = [], immediateClientErrorPathRules = []) {
|
|
17635
17844
|
switch (eventType) {
|
|
17636
17845
|
case "backend_exception":
|
|
17637
17846
|
case "frontend_exception":
|
|
@@ -17643,7 +17852,14 @@ function classifyEvent(eventType, logLevel, probeActivationId, payload, captureP
|
|
|
17643
17852
|
return "context_signal";
|
|
17644
17853
|
case "request_event": {
|
|
17645
17854
|
const responseStatus = getRequestResponseStatus(payload);
|
|
17646
|
-
return classifyRequestStatus({
|
|
17855
|
+
return classifyRequestStatus({
|
|
17856
|
+
responseStatus,
|
|
17857
|
+
requestPath: payload?.["path"],
|
|
17858
|
+
httpMethod: payload?.["method"],
|
|
17859
|
+
capturePreset,
|
|
17860
|
+
immediateClientErrorStatuses,
|
|
17861
|
+
immediateClientErrorPathRules
|
|
17862
|
+
});
|
|
17647
17863
|
}
|
|
17648
17864
|
case "frontend_breadcrumb":
|
|
17649
17865
|
case "deploy_metadata":
|
|
@@ -17981,6 +18197,7 @@ var STORAGE_BOOTSTRAP_STATEMENTS = [
|
|
|
17981
18197
|
capture_breadcrumbs text,
|
|
17982
18198
|
capture_probe_events text,
|
|
17983
18199
|
immediate_client_error_statuses jsonb,
|
|
18200
|
+
immediate_client_error_path_rules jsonb,
|
|
17984
18201
|
updated_at timestamptz NOT NULL DEFAULT now()
|
|
17985
18202
|
)
|
|
17986
18203
|
`,
|
|
@@ -19336,6 +19553,13 @@ var STORAGE_SCHEMA_MIGRATIONS = [
|
|
|
19336
19553
|
ON plan_cleanup_tasks (completed_at, next_attempt_at, created_at)
|
|
19337
19554
|
`
|
|
19338
19555
|
]
|
|
19556
|
+
}),
|
|
19557
|
+
defineStorageSchemaMigration({
|
|
19558
|
+
id: "202606080001_add_capture_policy_client_error_path_rules",
|
|
19559
|
+
description: "Add path-scoped client error incident promotion rules to capture policies.",
|
|
19560
|
+
statements: [
|
|
19561
|
+
"ALTER TABLE capture_policies ADD COLUMN IF NOT EXISTS immediate_client_error_path_rules jsonb"
|
|
19562
|
+
]
|
|
19339
19563
|
})
|
|
19340
19564
|
];
|
|
19341
19565
|
|
|
@@ -29036,7 +29260,7 @@ var CLI_USAGE_LINES = [
|
|
|
29036
29260
|
" debugbundle weekly-report update <channel-id> [--day-of-week <day>] [--hour-of-day <0-23>] [--timezone <iana>] [--config-json <json>] [--is-enabled <true|false>] [--auth-file <path>] [--json]",
|
|
29037
29261
|
" debugbundle weekly-report delete <channel-id> [--auth-file <path>] [--json]",
|
|
29038
29262
|
" debugbundle capture-policy get --project <id> [--auth-file <path>] [--json]",
|
|
29039
|
-
" debugbundle capture-policy set --project <id> [--preset <minimal|balanced|investigative>] [--override <key=value>] [--client-error-incidents <preset-default|none|recommended|custom>] [--client-error-statuses <400,401,...>] [--auth-file <path>] [--json]",
|
|
29263
|
+
" debugbundle capture-policy set --project <id> [--preset <minimal|balanced|investigative>] [--override <key=value>] [--client-error-incidents <preset-default|none|recommended|custom>] [--client-error-statuses <400,401,...>] [--client-error-path-rule <404=/path/*@GET,POST>] [--client-error-path-rules-json <json|null>] [--auth-file <path>] [--json]",
|
|
29040
29264
|
" debugbundle capture-rule list --project-id <id> [--auth-file <path>] [--json]",
|
|
29041
29265
|
" debugbundle capture-rule suggest <incident-id> [--auth-file <path>] [--json]",
|
|
29042
29266
|
" debugbundle capture-rule create-from-suggestion <incident-id> --suggestion-id <id> [--name <name>] [--description <text>] [--enabled <true|false>] [--expires-at <ISO8601>] [--auth-file <path>] [--json]",
|
|
@@ -32016,6 +32240,18 @@ function statusesEqual(left, right) {
|
|
|
32016
32240
|
function formatStatusList(statuses) {
|
|
32017
32241
|
return statuses.length === 0 ? "none" : statuses.join(", ");
|
|
32018
32242
|
}
|
|
32243
|
+
function formatClientErrorPathRules(response) {
|
|
32244
|
+
const rawOverride = response.overrides.immediate_client_error_path_rules ?? null;
|
|
32245
|
+
const rules = rawOverride ?? response.policy.immediate_client_error_path_rules ?? [];
|
|
32246
|
+
if (rules.length === 0) {
|
|
32247
|
+
return rawOverride === null ? "preset default (none)" : "none (explicit)";
|
|
32248
|
+
}
|
|
32249
|
+
const formatted = rules.map((rule) => {
|
|
32250
|
+
const methods = rule.methods.length === 0 ? "" : `@${rule.methods.join(",")}`;
|
|
32251
|
+
return `${rule.status_code}=${rule.path_pattern}${methods}`;
|
|
32252
|
+
});
|
|
32253
|
+
return `${rawOverride === null ? "preset default" : "custom"} (${formatted.join("; ")})`;
|
|
32254
|
+
}
|
|
32019
32255
|
function formatClientErrorIncidents(response) {
|
|
32020
32256
|
const rawOverride = response.overrides.immediate_client_error_statuses;
|
|
32021
32257
|
if (rawOverride === null) {
|
|
@@ -32037,7 +32273,8 @@ function formatPolicy(response) {
|
|
|
32037
32273
|
`capture_request_events: ${policy.capture_request_events}`,
|
|
32038
32274
|
`capture_breadcrumbs: ${policy.capture_breadcrumbs}`,
|
|
32039
32275
|
`capture_probe_events: ${policy.capture_probe_events}`,
|
|
32040
|
-
`client_error_incidents: ${formatClientErrorIncidents(response)}
|
|
32276
|
+
`client_error_incidents: ${formatClientErrorIncidents(response)}`,
|
|
32277
|
+
`client_error_path_rules: ${formatClientErrorPathRules(response)}`
|
|
32041
32278
|
].join("\n");
|
|
32042
32279
|
}
|
|
32043
32280
|
async function getCapturePolicyCommand(input2, api) {
|
|
@@ -32274,18 +32511,44 @@ function mapErrorToExitCode12(error) {
|
|
|
32274
32511
|
}
|
|
32275
32512
|
return 1;
|
|
32276
32513
|
}
|
|
32277
|
-
function
|
|
32514
|
+
function formatMatcherFromValue(matcher) {
|
|
32278
32515
|
const parts = [];
|
|
32279
|
-
const matcher = rule.matcher;
|
|
32280
32516
|
if (matcher.event_types !== void 0) {
|
|
32281
32517
|
parts.push(`event_types=${matcher.event_types.join(",")}`);
|
|
32282
32518
|
}
|
|
32283
32519
|
if (matcher.browser_event_kind !== void 0) {
|
|
32284
32520
|
parts.push(`browser_event_kind=${matcher.browser_event_kind}`);
|
|
32285
32521
|
}
|
|
32522
|
+
if (matcher.browser_event_opaque !== void 0) {
|
|
32523
|
+
parts.push(`browser_event_opaque=${String(matcher.browser_event_opaque)}`);
|
|
32524
|
+
}
|
|
32525
|
+
if (matcher.client_kind !== void 0) {
|
|
32526
|
+
parts.push(`client_kind=${matcher.client_kind}`);
|
|
32527
|
+
}
|
|
32528
|
+
if (matcher.bot_family !== void 0) {
|
|
32529
|
+
parts.push(`bot_family=${matcher.bot_family}`);
|
|
32530
|
+
}
|
|
32531
|
+
if (matcher.services !== void 0) {
|
|
32532
|
+
parts.push(`services=${matcher.services.join(",")}`);
|
|
32533
|
+
}
|
|
32534
|
+
if (matcher.environments !== void 0) {
|
|
32535
|
+
parts.push(`environments=${matcher.environments.join(",")}`);
|
|
32536
|
+
}
|
|
32537
|
+
if (matcher.message_equals !== void 0) {
|
|
32538
|
+
parts.push(`message_equals=${JSON.stringify(matcher.message_equals)}`);
|
|
32539
|
+
}
|
|
32540
|
+
if (matcher.message_contains !== void 0) {
|
|
32541
|
+
parts.push(`message_contains=${JSON.stringify(matcher.message_contains)}`);
|
|
32542
|
+
}
|
|
32543
|
+
if (matcher.error_name !== void 0) {
|
|
32544
|
+
parts.push(`error_name=${matcher.error_name}`);
|
|
32545
|
+
}
|
|
32286
32546
|
if (matcher.resource_url?.host !== void 0) {
|
|
32287
32547
|
parts.push(`resource_host=${matcher.resource_url.host}`);
|
|
32288
32548
|
}
|
|
32549
|
+
if (matcher.resource_url?.path_equals !== void 0) {
|
|
32550
|
+
parts.push(`resource_path=${matcher.resource_url.path_equals}`);
|
|
32551
|
+
}
|
|
32289
32552
|
if (matcher.request_url?.path_equals !== void 0) {
|
|
32290
32553
|
parts.push(`request_path=${matcher.request_url.path_equals}`);
|
|
32291
32554
|
}
|
|
@@ -32297,6 +32560,9 @@ function formatMatcher(rule) {
|
|
|
32297
32560
|
}
|
|
32298
32561
|
return parts.length > 0 ? parts.join(" ") : "matcher=custom";
|
|
32299
32562
|
}
|
|
32563
|
+
function formatMatcher(rule) {
|
|
32564
|
+
return formatMatcherFromValue(rule.matcher);
|
|
32565
|
+
}
|
|
32300
32566
|
function formatRule(rule) {
|
|
32301
32567
|
const action = rule.action === "sample" ? `${rule.action}:${rule.sample_rate ?? "?"}:${rule.sample_event_class ?? "?"}` : rule.action;
|
|
32302
32568
|
return [
|
|
@@ -32317,7 +32583,10 @@ function formatSuggestionResponse(response) {
|
|
|
32317
32583
|
return response.suggestions.map(
|
|
32318
32584
|
(suggestion) => [
|
|
32319
32585
|
`${suggestion.suggestion_id} ${suggestion.recommended_action} ${suggestion.confidence} ${suggestion.label}`,
|
|
32320
|
-
suggestion.reason
|
|
32586
|
+
suggestion.reason,
|
|
32587
|
+
`matcher: ${formatMatcherFromValue(suggestion.rule.matcher)}`,
|
|
32588
|
+
`requires_confirmation: ${String(suggestion.requires_confirmation)}`,
|
|
32589
|
+
`apply: debugbundle capture-rule create-from-suggestion <incident-id> --suggestion-id ${suggestion.suggestion_id}`
|
|
32321
32590
|
].join("\n")
|
|
32322
32591
|
).join("\n\n");
|
|
32323
32592
|
}
|
|
@@ -32810,6 +33079,31 @@ async function handleCapturePolicyCommand(parsedArgv, dependencies) {
|
|
|
32810
33079
|
}
|
|
32811
33080
|
return normalized;
|
|
32812
33081
|
}
|
|
33082
|
+
function parseClientErrorPathRuleOption(value) {
|
|
33083
|
+
const separatorIndex = value.indexOf("=");
|
|
33084
|
+
if (separatorIndex <= 0 || separatorIndex === value.length - 1) {
|
|
33085
|
+
throw new CliInputError("Invalid value for --client-error-path-rule.");
|
|
33086
|
+
}
|
|
33087
|
+
const status = Number(value.slice(0, separatorIndex));
|
|
33088
|
+
if (!Number.isInteger(status) || status < 400 || status > 499) {
|
|
33089
|
+
throw new CliInputError("Invalid value for --client-error-path-rule.");
|
|
33090
|
+
}
|
|
33091
|
+
const ruleValue = value.slice(separatorIndex + 1);
|
|
33092
|
+
const methodSeparatorIndex = ruleValue.lastIndexOf("@");
|
|
33093
|
+
const pathPattern = methodSeparatorIndex === -1 ? ruleValue : ruleValue.slice(0, methodSeparatorIndex);
|
|
33094
|
+
const methods = methodSeparatorIndex === -1 ? [] : ruleValue.slice(methodSeparatorIndex + 1).split(",").map((method) => method.trim().toUpperCase()).filter((method) => method.length > 0);
|
|
33095
|
+
const parsed = ImmediateClientErrorPathRulesSchema.safeParse([
|
|
33096
|
+
{
|
|
33097
|
+
status_code: status,
|
|
33098
|
+
path_pattern: pathPattern,
|
|
33099
|
+
methods
|
|
33100
|
+
}
|
|
33101
|
+
]);
|
|
33102
|
+
if (!parsed.success || parsed.data[0] === void 0) {
|
|
33103
|
+
throw new CliInputError("Invalid value for --client-error-path-rule.");
|
|
33104
|
+
}
|
|
33105
|
+
return parsed.data[0];
|
|
33106
|
+
}
|
|
32813
33107
|
const action = requirePositional(parsedArgv, 1, "action");
|
|
32814
33108
|
if (action === "get") {
|
|
32815
33109
|
expectNoUnknownOptions(parsedArgv, ["auth-file", "json", "project"]);
|
|
@@ -32830,7 +33124,9 @@ async function handleCapturePolicyCommand(parsedArgv, dependencies) {
|
|
|
32830
33124
|
"preset",
|
|
32831
33125
|
"override",
|
|
32832
33126
|
"client-error-incidents",
|
|
32833
|
-
"client-error-statuses"
|
|
33127
|
+
"client-error-statuses",
|
|
33128
|
+
"client-error-path-rule",
|
|
33129
|
+
"client-error-path-rules-json"
|
|
32834
33130
|
]);
|
|
32835
33131
|
ensureNoExtraPositionals(parsedArgv, 2);
|
|
32836
33132
|
const projectId = readStringOption(parsedArgv, "project");
|
|
@@ -32857,9 +33153,14 @@ async function handleCapturePolicyCommand(parsedArgv, dependencies) {
|
|
|
32857
33153
|
}
|
|
32858
33154
|
const clientErrorIncidents = readStringOption(parsedArgv, "client-error-incidents");
|
|
32859
33155
|
const clientErrorStatuses = readStringOption(parsedArgv, "client-error-statuses");
|
|
33156
|
+
const clientErrorPathRuleOptions = readStringListOption(parsedArgv, "client-error-path-rule") ?? [];
|
|
33157
|
+
const clientErrorPathRulesJson = readJsonOption(parsedArgv, "client-error-path-rules-json");
|
|
32860
33158
|
if (clientErrorStatuses !== void 0 && clientErrorIncidents !== "custom") {
|
|
32861
33159
|
throw new CliInputError("Use --client-error-statuses only with --client-error-incidents custom.");
|
|
32862
33160
|
}
|
|
33161
|
+
if (clientErrorPathRuleOptions.length > 0 && clientErrorPathRulesJson !== void 0) {
|
|
33162
|
+
throw new CliInputError("Use either --client-error-path-rule or --client-error-path-rules-json, not both.");
|
|
33163
|
+
}
|
|
32863
33164
|
if (clientErrorIncidents !== void 0) {
|
|
32864
33165
|
switch (clientErrorIncidents) {
|
|
32865
33166
|
case "preset-default":
|
|
@@ -32881,6 +33182,22 @@ async function handleCapturePolicyCommand(parsedArgv, dependencies) {
|
|
|
32881
33182
|
throw new CliInputError("Invalid value for --client-error-incidents.");
|
|
32882
33183
|
}
|
|
32883
33184
|
}
|
|
33185
|
+
if (clientErrorPathRulesJson !== void 0) {
|
|
33186
|
+
if (clientErrorPathRulesJson === null) {
|
|
33187
|
+
update.immediate_client_error_path_rules = null;
|
|
33188
|
+
} else {
|
|
33189
|
+
const parsed = ImmediateClientErrorPathRulesSchema.safeParse(clientErrorPathRulesJson);
|
|
33190
|
+
if (!parsed.success) {
|
|
33191
|
+
throw new CliInputError("Invalid value for --client-error-path-rules-json.");
|
|
33192
|
+
}
|
|
33193
|
+
update.immediate_client_error_path_rules = parsed.data;
|
|
33194
|
+
}
|
|
33195
|
+
}
|
|
33196
|
+
if (clientErrorPathRuleOptions.length > 0) {
|
|
33197
|
+
update.immediate_client_error_path_rules = ImmediateClientErrorPathRulesSchema.parse(
|
|
33198
|
+
clientErrorPathRuleOptions.map(parseClientErrorPathRuleOption)
|
|
33199
|
+
);
|
|
33200
|
+
}
|
|
32884
33201
|
if (Object.keys(update).length === 0) {
|
|
32885
33202
|
throw new CliInputError("At least one capture policy field must be provided.");
|
|
32886
33203
|
}
|
|
@@ -34586,7 +34903,7 @@ async function handleCaptureRuleCommand2(parsedArgv, dependencies) {
|
|
|
34586
34903
|
// package.json
|
|
34587
34904
|
var package_default = {
|
|
34588
34905
|
name: "@debugbundle/cli",
|
|
34589
|
-
version: "1.
|
|
34906
|
+
version: "1.3.0",
|
|
34590
34907
|
private: false,
|
|
34591
34908
|
description: "Command-line interface for DebugBundle",
|
|
34592
34909
|
license: "AGPL-3.0-only",
|