@agent-native/core 0.133.2 → 0.134.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/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +62 -0
- package/corpus/core/docs/content/observability.mdx +41 -1
- package/corpus/core/docs/content/tracking.mdx +25 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/agent/run-manager.ts +7 -0
- package/corpus/core/src/client/agent-chat-adapter.ts +10 -0
- package/corpus/core/src/client/analytics.ts +105 -1
- package/corpus/core/src/client/use-action.ts +6 -0
- package/corpus/core/src/deploy/build.ts +38 -1
- package/corpus/core/src/observability/posthog-ai.ts +294 -0
- package/corpus/core/src/observability/routes.ts +29 -6
- package/corpus/core/src/observability/traces.ts +287 -12
- package/corpus/core/src/observability/types.ts +11 -0
- package/corpus/core/src/secrets/register-framework-secrets.ts +16 -0
- package/corpus/core/src/server/agent-run-context.ts +21 -0
- package/corpus/core/src/server/capture-error.ts +8 -0
- package/corpus/core/src/server/core-routes-plugin.ts +75 -4
- package/corpus/core/src/server/deploy-environment.ts +57 -0
- package/corpus/core/src/server/error-noise-filter.ts +268 -0
- package/corpus/core/src/server/posthog-config.ts +75 -0
- package/corpus/core/src/server/request-context.ts +6 -0
- package/corpus/core/src/server/sentry-config.ts +4 -8
- package/corpus/core/src/server/sentry-plugin.ts +13 -29
- package/corpus/core/src/server/sentry.ts +13 -156
- package/corpus/core/src/server/ssr-handler.ts +6 -1
- package/corpus/core/src/shared/mcp-embed-headers.ts +1 -1
- package/corpus/core/src/templates/workspace-core/.agents/skills/observability/SKILL.md +36 -10
- package/corpus/core/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +55 -1
- package/corpus/core/src/tracking/error-capture.ts +44 -109
- package/corpus/core/src/tracking/index.ts +11 -0
- package/corpus/core/src/tracking/posthog-exception.ts +305 -0
- package/corpus/core/src/tracking/providers.ts +91 -14
- package/corpus/core/src/tracking/redaction.ts +105 -0
- package/corpus/templates/content/actions/_batch-utils.ts +33 -0
- package/corpus/templates/content/actions/_builder-cms-read-client.ts +173 -81
- package/corpus/templates/content/actions/_content-files.ts +31 -21
- package/corpus/templates/content/actions/_database-source-utils.ts +653 -155
- package/corpus/templates/content/actions/_database-utils.ts +535 -41
- package/corpus/templates/content/actions/add-content-database-source-field-property.ts +291 -240
- package/corpus/templates/content/actions/add-database-item.ts +15 -1
- package/corpus/templates/content/actions/attach-content-database-source.ts +156 -58
- package/corpus/templates/content/actions/bind-content-database-source-field.ts +2 -2
- package/corpus/templates/content/actions/cancel-prepared-builder-source-update.ts +4 -1
- package/corpus/templates/content/actions/delete-database-items.ts +8 -2
- package/corpus/templates/content/actions/disconnect-content-database-source.ts +2 -2
- package/corpus/templates/content/actions/duplicate-database-item.ts +15 -1
- package/corpus/templates/content/actions/duplicate-database-items.ts +19 -1
- package/corpus/templates/content/actions/execute-builder-source-execution.ts +2 -1
- package/corpus/templates/content/actions/get-content-database.ts +12 -64
- package/corpus/templates/content/actions/move-database-item.ts +4 -1
- package/corpus/templates/content/actions/prepare-builder-source-execution.ts +1 -1
- package/corpus/templates/content/actions/prepare-builder-source-review.ts +4 -8
- package/corpus/templates/content/actions/preview-content-database-source-attach.ts +92 -0
- package/corpus/templates/content/actions/process-builder-body-hydration.ts +2 -1
- package/corpus/templates/content/actions/query-content-database-items.ts +64 -0
- package/corpus/templates/content/actions/refresh-content-database-source.ts +7 -0
- package/corpus/templates/content/actions/review-content-database-source-change-set.ts +1 -1
- package/corpus/templates/content/actions/set-content-database-source-write-mode.ts +1 -1
- package/corpus/templates/content/actions/stage-builder-revision.ts +1 -1
- package/corpus/templates/content/actions/update-content-database-personal-view.ts +29 -3
- package/corpus/templates/content/actions/update-content-database-view.ts +1 -1
- package/corpus/templates/content/actions/validate-builder-source-execution.ts +1 -1
- package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +3 -22
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +267 -105
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +82 -1
- package/corpus/templates/content/app/hooks/use-content-database.ts +285 -24
- package/corpus/templates/content/app/hooks/use-document-properties.ts +7 -6
- package/corpus/templates/content/app/i18n-data.ts +10 -0
- package/corpus/templates/content/changelog/2026-07-29-large-databases-keep-useful-rows-visible.md +6 -0
- package/corpus/templates/content/changelog/2026-07-30-builder-source-columns-now-appear-immediately-when-connected.md +6 -0
- package/corpus/templates/content/changelog/2026-07-30-large-builder-backed-tables-show-useful-rows-sooner-and-fini.md +6 -0
- package/corpus/templates/content/changelog/2026-08-01-large-builder-databases-now-show-rows-immediately-and-finish.md +6 -0
- package/corpus/templates/content/parity/matrix.md +2 -1
- package/corpus/templates/content/parity/matrix.ts +25 -0
- package/corpus/templates/content/shared/api.ts +54 -4
- package/corpus/templates/content/shared/database-query.ts +359 -0
- package/dist/agent/run-manager.d.ts.map +1 -1
- package/dist/agent/run-manager.js +7 -0
- package/dist/agent/run-manager.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +12 -0
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/analytics.d.ts +8 -0
- package/dist/client/analytics.d.ts.map +1 -1
- package/dist/client/analytics.js +95 -1
- package/dist/client/analytics.js.map +1 -1
- package/dist/client/use-action.d.ts.map +1 -1
- package/dist/client/use-action.js +6 -0
- package/dist/client/use-action.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +38 -1
- package/dist/deploy/build.js.map +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/posthog-ai.d.ts +126 -0
- package/dist/observability/posthog-ai.d.ts.map +1 -0
- package/dist/observability/posthog-ai.js +190 -0
- package/dist/observability/posthog-ai.js.map +1 -0
- package/dist/observability/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts.map +1 -1
- package/dist/observability/routes.js +26 -6
- package/dist/observability/routes.js.map +1 -1
- package/dist/observability/traces.d.ts +9 -0
- package/dist/observability/traces.d.ts.map +1 -1
- package/dist/observability/traces.js +219 -10
- package/dist/observability/traces.js.map +1 -1
- package/dist/observability/types.d.ts +10 -0
- package/dist/observability/types.d.ts.map +1 -1
- package/dist/observability/types.js +1 -0
- package/dist/observability/types.js.map +1 -1
- package/dist/secrets/register-framework-secrets.d.ts.map +1 -1
- package/dist/secrets/register-framework-secrets.js +14 -0
- package/dist/secrets/register-framework-secrets.js.map +1 -1
- package/dist/server/agent-run-context.d.ts +8 -0
- package/dist/server/agent-run-context.d.ts.map +1 -1
- package/dist/server/agent-run-context.js +18 -0
- package/dist/server/agent-run-context.js.map +1 -1
- package/dist/server/capture-error.d.ts +8 -0
- package/dist/server/capture-error.d.ts.map +1 -1
- package/dist/server/capture-error.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts +0 -23
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +71 -7
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/deploy-environment.d.ts +17 -0
- package/dist/server/deploy-environment.d.ts.map +1 -0
- package/dist/server/deploy-environment.js +47 -0
- package/dist/server/deploy-environment.js.map +1 -0
- package/dist/server/error-noise-filter.d.ts +80 -0
- package/dist/server/error-noise-filter.d.ts.map +1 -0
- package/dist/server/error-noise-filter.js +173 -0
- package/dist/server/error-noise-filter.js.map +1 -0
- package/dist/server/posthog-config.d.ts +28 -0
- package/dist/server/posthog-config.d.ts.map +1 -0
- package/dist/server/posthog-config.js +53 -0
- package/dist/server/posthog-config.js.map +1 -0
- package/dist/server/request-context.d.ts +6 -0
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/request-context.js.map +1 -1
- package/dist/server/sentry-config.d.ts +1 -0
- package/dist/server/sentry-config.d.ts.map +1 -1
- package/dist/server/sentry-config.js +3 -1
- package/dist/server/sentry-config.js.map +1 -1
- package/dist/server/sentry-plugin.d.ts.map +1 -1
- package/dist/server/sentry-plugin.js +12 -27
- package/dist/server/sentry-plugin.js.map +1 -1
- package/dist/server/sentry.d.ts.map +1 -1
- package/dist/server/sentry.js +8 -124
- package/dist/server/sentry.js.map +1 -1
- package/dist/server/ssr-handler.d.ts.map +1 -1
- package/dist/server/ssr-handler.js +6 -1
- package/dist/server/ssr-handler.js.map +1 -1
- package/dist/shared/mcp-embed-headers.d.ts +1 -1
- package/dist/shared/mcp-embed-headers.d.ts.map +1 -1
- package/dist/shared/mcp-embed-headers.js +1 -1
- package/dist/shared/mcp-embed-headers.js.map +1 -1
- package/dist/templates/workspace-core/.agents/skills/observability/SKILL.md +36 -10
- package/dist/templates/workspace-core/.agents/skills/tracking/SKILL.md +55 -1
- package/dist/tracking/error-capture.d.ts +7 -0
- package/dist/tracking/error-capture.d.ts.map +1 -1
- package/dist/tracking/error-capture.js +10 -73
- package/dist/tracking/error-capture.js.map +1 -1
- package/dist/tracking/index.d.ts +1 -0
- package/dist/tracking/index.d.ts.map +1 -1
- package/dist/tracking/index.js +1 -0
- package/dist/tracking/index.js.map +1 -1
- package/dist/tracking/posthog-exception.d.ts +103 -0
- package/dist/tracking/posthog-exception.d.ts.map +1 -0
- package/dist/tracking/posthog-exception.js +181 -0
- package/dist/tracking/posthog-exception.js.map +1 -0
- package/dist/tracking/providers.d.ts +14 -0
- package/dist/tracking/providers.d.ts.map +1 -1
- package/dist/tracking/providers.js +63 -11
- package/dist/tracking/providers.js.map +1 -1
- package/dist/tracking/redaction.d.ts +25 -0
- package/dist/tracking/redaction.d.ts.map +1 -0
- package/dist/tracking/redaction.js +85 -0
- package/dist/tracking/redaction.js.map +1 -0
- package/docs/content/observability.mdx +41 -1
- package/docs/content/tracking.mdx +25 -0
- package/package.json +1 -1
- package/src/agent/run-manager.ts +7 -0
- package/src/client/agent-chat-adapter.ts +10 -0
- package/src/client/analytics.ts +105 -1
- package/src/client/use-action.ts +6 -0
- package/src/deploy/build.ts +38 -1
- package/src/observability/posthog-ai.ts +294 -0
- package/src/observability/routes.ts +29 -6
- package/src/observability/traces.ts +287 -12
- package/src/observability/types.ts +11 -0
- package/src/secrets/register-framework-secrets.ts +16 -0
- package/src/server/agent-run-context.ts +21 -0
- package/src/server/capture-error.ts +8 -0
- package/src/server/core-routes-plugin.ts +75 -4
- package/src/server/deploy-environment.ts +57 -0
- package/src/server/error-noise-filter.ts +268 -0
- package/src/server/posthog-config.ts +75 -0
- package/src/server/request-context.ts +6 -0
- package/src/server/sentry-config.ts +4 -8
- package/src/server/sentry-plugin.ts +13 -29
- package/src/server/sentry.ts +13 -156
- package/src/server/ssr-handler.ts +6 -1
- package/src/shared/mcp-embed-headers.ts +1 -1
- package/src/templates/workspace-core/.agents/skills/observability/SKILL.md +36 -10
- package/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +55 -1
- package/src/tracking/error-capture.ts +44 -109
- package/src/tracking/index.ts +11 -0
- package/src/tracking/posthog-exception.ts +305 -0
- package/src/tracking/providers.ts +91 -14
- package/src/tracking/redaction.ts +105 -0
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* automatically by the core-routes plugin).
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
+
import { reshapeTrackedExceptionProperties } from "./posthog-exception.js";
|
|
16
17
|
import { registerTrackingProvider } from "./registry.js";
|
|
17
18
|
import type { TrackingProvider, TrackingEvent } from "./types.js";
|
|
18
19
|
|
|
@@ -162,27 +163,61 @@ function isPostHogAiObservabilityEvent(eventName: string): boolean {
|
|
|
162
163
|
return eventName.startsWith("$ai_");
|
|
163
164
|
}
|
|
164
165
|
|
|
165
|
-
|
|
166
|
+
/**
|
|
167
|
+
* `$ai_*` and `$exception` are ingested through PostHog's dedicated endpoint
|
|
168
|
+
* rather than `/capture/`, and `$exception` additionally has to carry
|
|
169
|
+
* `$exception_list` — the framework's own `captureException()` emits camelCase
|
|
170
|
+
* fields that PostHog would otherwise render as an empty, ungroupable issue.
|
|
171
|
+
*/
|
|
172
|
+
function createPostHogProvider(
|
|
173
|
+
apiKey: string,
|
|
174
|
+
host: string,
|
|
175
|
+
errorTracking: boolean,
|
|
176
|
+
): TrackingProvider {
|
|
177
|
+
const sendToEventsEndpoint = (
|
|
178
|
+
event: TrackingEvent,
|
|
179
|
+
properties: Record<string, unknown> | undefined,
|
|
180
|
+
distinctId: string,
|
|
181
|
+
): void => {
|
|
182
|
+
enqueue(
|
|
183
|
+
`${host}/i/v0/e/`,
|
|
184
|
+
JSON.stringify({
|
|
185
|
+
api_key: apiKey,
|
|
186
|
+
event: event.name,
|
|
187
|
+
properties: {
|
|
188
|
+
distinct_id: distinctId,
|
|
189
|
+
...properties,
|
|
190
|
+
timestamp: event.timestamp,
|
|
191
|
+
},
|
|
192
|
+
}),
|
|
193
|
+
);
|
|
194
|
+
};
|
|
195
|
+
|
|
166
196
|
return {
|
|
167
197
|
name: "posthog",
|
|
168
198
|
track(event: TrackingEvent) {
|
|
169
199
|
const distinctId = event.userId || "anonymous";
|
|
170
200
|
if (isPostHogAiObservabilityEvent(event.name)) {
|
|
171
|
-
|
|
172
|
-
`${host}/i/v0/e/`,
|
|
173
|
-
JSON.stringify({
|
|
174
|
-
api_key: apiKey,
|
|
175
|
-
event: event.name,
|
|
176
|
-
properties: {
|
|
177
|
-
distinct_id: distinctId,
|
|
178
|
-
...event.properties,
|
|
179
|
-
timestamp: event.timestamp,
|
|
180
|
-
},
|
|
181
|
-
}),
|
|
182
|
-
);
|
|
201
|
+
sendToEventsEndpoint(event, event.properties, distinctId);
|
|
183
202
|
return;
|
|
184
203
|
}
|
|
185
204
|
|
|
205
|
+
if (event.name === "$exception") {
|
|
206
|
+
// `POSTHOG_ERROR_TRACKING=false` keeps product analytics flowing while
|
|
207
|
+
// another backend owns crashes. Drop rather than downgrade to
|
|
208
|
+
// `/capture/`: a malformed exception is what this branch exists to
|
|
209
|
+
// prevent.
|
|
210
|
+
if (!errorTracking) return;
|
|
211
|
+
const reshaped = reshapeTrackedExceptionProperties(event.properties);
|
|
212
|
+
if (reshaped) {
|
|
213
|
+
sendToEventsEndpoint(event, reshaped, distinctId);
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
// No recognizable exception fields. Fall through to `/capture/` so the
|
|
217
|
+
// event is still recorded as-is rather than becoming an issue with
|
|
218
|
+
// nothing in it.
|
|
219
|
+
}
|
|
220
|
+
|
|
186
221
|
enqueue(
|
|
187
222
|
`${host}/capture/`,
|
|
188
223
|
JSON.stringify({
|
|
@@ -213,6 +248,42 @@ function createPostHogProvider(apiKey: string, host: string): TrackingProvider {
|
|
|
213
248
|
};
|
|
214
249
|
}
|
|
215
250
|
|
|
251
|
+
/**
|
|
252
|
+
* Send one event to PostHog only, bypassing the provider fan-out.
|
|
253
|
+
*
|
|
254
|
+
* For payloads whose *shape* is PostHog-specific and whose *content* other
|
|
255
|
+
* backends must not receive. `track()` broadcasts to every configured provider,
|
|
256
|
+
* so a PostHog-only integration (e.g. enabling a survey id) would otherwise
|
|
257
|
+
* start exporting that integration's content — including user-authored text —
|
|
258
|
+
* to Mixpanel, Amplitude, webhooks, and Agent Native Analytics as a side
|
|
259
|
+
* effect nobody opted into.
|
|
260
|
+
*
|
|
261
|
+
* Returns `false` when PostHog is not configured, so callers can tell "not
|
|
262
|
+
* sent" from "sent".
|
|
263
|
+
*/
|
|
264
|
+
export function sendPostHogEvent(
|
|
265
|
+
name: string,
|
|
266
|
+
properties: Record<string, unknown>,
|
|
267
|
+
distinctId: string,
|
|
268
|
+
): boolean {
|
|
269
|
+
const apiKey = process.env.POSTHOG_API_KEY;
|
|
270
|
+
if (!apiKey) return false;
|
|
271
|
+
const host = (process.env.POSTHOG_HOST || POSTHOG_DEFAULT_HOST).replace(
|
|
272
|
+
/\/+$/,
|
|
273
|
+
"",
|
|
274
|
+
);
|
|
275
|
+
enqueue(
|
|
276
|
+
`${host}/capture/`,
|
|
277
|
+
JSON.stringify({
|
|
278
|
+
api_key: apiKey,
|
|
279
|
+
event: name,
|
|
280
|
+
distinct_id: distinctId,
|
|
281
|
+
properties: { ...properties, timestamp: new Date().toISOString() },
|
|
282
|
+
}),
|
|
283
|
+
);
|
|
284
|
+
return true;
|
|
285
|
+
}
|
|
286
|
+
|
|
216
287
|
// ─── Mixpanel ──────────────────────────────────────────────────────────────
|
|
217
288
|
|
|
218
289
|
function createMixpanelProvider(token: string): TrackingProvider {
|
|
@@ -383,7 +454,13 @@ export function registerBuiltinProviders(): void {
|
|
|
383
454
|
/\/+$/,
|
|
384
455
|
"",
|
|
385
456
|
);
|
|
386
|
-
registerTrackingProvider(
|
|
457
|
+
registerTrackingProvider(
|
|
458
|
+
createPostHogProvider(
|
|
459
|
+
posthogKey,
|
|
460
|
+
host,
|
|
461
|
+
process.env.POSTHOG_ERROR_TRACKING?.trim().toLowerCase() !== "false",
|
|
462
|
+
),
|
|
463
|
+
);
|
|
387
464
|
}
|
|
388
465
|
|
|
389
466
|
const mixpanelToken = process.env.MIXPANEL_TOKEN;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bounding and redaction helpers shared by every exception emitter.
|
|
3
|
+
*
|
|
4
|
+
* Kept free of `process.env` and Node built-ins so the browser bundle can use
|
|
5
|
+
* the same rules — an exception shaped one way on the server and another way
|
|
6
|
+
* in the client is how a leak ships in only one of them.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export const MAX_MESSAGE_LENGTH = 1000;
|
|
10
|
+
export const MAX_STACK_LENGTH = 8000;
|
|
11
|
+
export const MAX_TAGS = 30;
|
|
12
|
+
export const MAX_EXTRA_KEYS = 30;
|
|
13
|
+
export const MAX_EXTRA_VALUE_LENGTH = 1000;
|
|
14
|
+
|
|
15
|
+
const SECRET_RE = /\b(?:bearer|basic)\s+[^\s]+/gi;
|
|
16
|
+
|
|
17
|
+
export const SECRET_KEY_RE =
|
|
18
|
+
/(?:authorization|cookie|set[-_]?cookie|token|secret|password|passwd|pwd|api[-_]?key|apikey|credential)/i;
|
|
19
|
+
|
|
20
|
+
export function redact(value: string): string {
|
|
21
|
+
return value
|
|
22
|
+
.replace(SECRET_RE, (match) => `${match.split(/\s+/, 1)[0]} <redacted>`)
|
|
23
|
+
.replace(
|
|
24
|
+
/([A-Za-z0-9_$.-]*(?:authorization|cookie|token|secret|password|passwd|pwd|api[-_]?key|apikey|credential)[A-Za-z0-9_$.-]*\s*[:=]\s*)([^\s,;}]+)/gi,
|
|
25
|
+
"$1<redacted>",
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function boundedText(value: unknown, max: number): string {
|
|
30
|
+
const text = typeof value === "string" ? value : String(value ?? "");
|
|
31
|
+
const safe = redact(text);
|
|
32
|
+
return safe.length > max ? safe.slice(0, max) : safe;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function safeValue(value: unknown, depth = 2): unknown {
|
|
36
|
+
if (
|
|
37
|
+
value == null ||
|
|
38
|
+
typeof value === "boolean" ||
|
|
39
|
+
typeof value === "number"
|
|
40
|
+
) {
|
|
41
|
+
return value;
|
|
42
|
+
}
|
|
43
|
+
if (typeof value === "string")
|
|
44
|
+
return boundedText(value, MAX_EXTRA_VALUE_LENGTH);
|
|
45
|
+
if (depth <= 0) return boundedText(value, MAX_EXTRA_VALUE_LENGTH);
|
|
46
|
+
if (Array.isArray(value)) {
|
|
47
|
+
return value.slice(0, 20).map((item) => safeValue(item, depth - 1));
|
|
48
|
+
}
|
|
49
|
+
if (typeof value === "object") {
|
|
50
|
+
const out: Record<string, unknown> = {};
|
|
51
|
+
for (const [key, child] of Object.entries(value)) {
|
|
52
|
+
if (Object.keys(out).length >= MAX_EXTRA_KEYS) break;
|
|
53
|
+
const safeKey = boundedText(key, 100);
|
|
54
|
+
out[safeKey] = SECRET_KEY_RE.test(safeKey)
|
|
55
|
+
? "<redacted>"
|
|
56
|
+
: safeValue(child, depth - 1);
|
|
57
|
+
}
|
|
58
|
+
return out;
|
|
59
|
+
}
|
|
60
|
+
return boundedText(value, MAX_EXTRA_VALUE_LENGTH);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function safeTags(
|
|
64
|
+
tags: Record<string, string | undefined> | undefined,
|
|
65
|
+
): Record<string, string> {
|
|
66
|
+
const out: Record<string, string> = {};
|
|
67
|
+
for (const [key, value] of Object.entries(tags ?? {})) {
|
|
68
|
+
if (Object.keys(out).length >= MAX_TAGS) break;
|
|
69
|
+
// Skip, don't stop: callers build tag objects with optional entries
|
|
70
|
+
// (`{ ...tags, route, method, userAgent }`), so breaking on the first
|
|
71
|
+
// undefined dropped every tag after it depending on key order.
|
|
72
|
+
if (value == null) continue;
|
|
73
|
+
const safeKey = boundedText(key, 100);
|
|
74
|
+
out[safeKey] = SECRET_KEY_RE.test(safeKey)
|
|
75
|
+
? "<redacted>"
|
|
76
|
+
: boundedText(value, 200);
|
|
77
|
+
}
|
|
78
|
+
return out;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface ExceptionParts {
|
|
82
|
+
type: string;
|
|
83
|
+
message: string;
|
|
84
|
+
stack?: string;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Split an unknown thrown value into bounded, redacted type/message/stack. */
|
|
88
|
+
export function exceptionParts(error: unknown): ExceptionParts {
|
|
89
|
+
if (error instanceof Error) {
|
|
90
|
+
return {
|
|
91
|
+
type: boundedText(error.name || "Error", 200),
|
|
92
|
+
message: boundedText(
|
|
93
|
+
error.message || error.name || "Error",
|
|
94
|
+
MAX_MESSAGE_LENGTH,
|
|
95
|
+
),
|
|
96
|
+
...(error.stack
|
|
97
|
+
? { stack: boundedText(error.stack, MAX_STACK_LENGTH) }
|
|
98
|
+
: {}),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
type: "Error",
|
|
103
|
+
message: boundedText(error, MAX_MESSAGE_LENGTH),
|
|
104
|
+
};
|
|
105
|
+
}
|