@senpi/runtime 3.0.6-dev.runtime-phase-2.20260630134327 → 3.0.6-dev.runtime-phase-2.20260630134410
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/actions/llm-decision/anthropic-llm-decision.d.ts +5 -9
- package/dist/actions/llm-decision/anthropic-llm-decision.d.ts.map +1 -1
- package/dist/actions/llm-decision/anthropic-llm-decision.js +6 -86
- package/dist/actions/llm-decision/anthropic-llm-decision.js.map +1 -1
- package/dist/actions/llm-decision/factory.d.ts +0 -6
- package/dist/actions/llm-decision/factory.d.ts.map +1 -1
- package/dist/actions/llm-decision/factory.js +0 -2
- package/dist/actions/llm-decision/factory.js.map +1 -1
- package/dist/actions/llm-decision/openclaw-llm-decision.d.ts.map +1 -1
- package/dist/actions/llm-decision/openclaw-llm-decision.js +20 -0
- package/dist/actions/llm-decision/openclaw-llm-decision.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23 -11
- package/dist/index.js.map +1 -1
- package/dist/recording/wiring/emitter-factory.d.ts +0 -5
- package/dist/recording/wiring/emitter-factory.d.ts.map +1 -1
- package/dist/recording/wiring/emitter-factory.js +0 -18
- package/dist/recording/wiring/emitter-factory.js.map +1 -1
- package/dist/recording/wiring/index.d.ts +1 -1
- package/dist/recording/wiring/index.d.ts.map +1 -1
- package/dist/recording/wiring/index.js +1 -1
- package/dist/recording/wiring/index.js.map +1 -1
- package/dist/runtime/runtime-schema.d.ts +4 -53
- package/dist/runtime/runtime-schema.d.ts.map +1 -1
- package/dist/runtime/runtime-schema.js +4 -4
- package/dist/runtime/runtime-schema.js.map +1 -1
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +9 -15
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/senpi/client.d.ts +10 -0
- package/dist/senpi/client.d.ts.map +1 -1
- package/dist/senpi/client.js +69 -49
- package/dist/senpi/client.js.map +1 -1
- package/dist/telemetry/metrics.d.ts +47 -0
- package/dist/telemetry/metrics.d.ts.map +1 -0
- package/dist/telemetry/metrics.js +154 -0
- package/dist/telemetry/metrics.js.map +1 -0
- package/dist/telemetry/otel-sdk.d.ts +21 -33
- package/dist/telemetry/otel-sdk.d.ts.map +1 -1
- package/dist/telemetry/otel-sdk.js +77 -50
- package/dist/telemetry/otel-sdk.js.map +1 -1
- package/dist/telemetry/tracing.d.ts +2 -1
- package/dist/telemetry/tracing.d.ts.map +1 -1
- package/dist/telemetry/tracing.js +1 -1
- package/dist/telemetry/tracing.js.map +1 -1
- package/dist/tracking/spans/constants.d.ts +4 -11
- package/dist/tracking/spans/constants.d.ts.map +1 -1
- package/dist/tracking/spans/constants.js +4 -23
- package/dist/tracking/spans/constants.js.map +1 -1
- package/dist/tracking/spans/gen-ai.d.ts +70 -0
- package/dist/tracking/spans/gen-ai.d.ts.map +1 -0
- package/dist/tracking/spans/gen-ai.js +330 -0
- package/dist/tracking/spans/gen-ai.js.map +1 -0
- package/dist/tracking/spans/index.d.ts +6 -8
- package/dist/tracking/spans/index.d.ts.map +1 -1
- package/dist/tracking/spans/index.js +6 -11
- package/dist/tracking/spans/index.js.map +1 -1
- package/dist/tracking/spans/redact-pii.d.ts +18 -20
- package/dist/tracking/spans/redact-pii.d.ts.map +1 -1
- package/dist/tracking/spans/redact-pii.js +30 -29
- package/dist/tracking/spans/redact-pii.js.map +1 -1
- package/dist/tracking/spans/span-hooks.d.ts +0 -17
- package/dist/tracking/spans/span-hooks.d.ts.map +1 -1
- package/dist/tracking/spans/span-hooks.js +407 -207
- package/dist/tracking/spans/span-hooks.js.map +1 -1
- package/package.json +1 -1
- package/dist/tracking/spans/fan-out-span-transport.d.ts +0 -22
- package/dist/tracking/spans/fan-out-span-transport.d.ts.map +0 -1
- package/dist/tracking/spans/fan-out-span-transport.js +0 -49
- package/dist/tracking/spans/fan-out-span-transport.js.map +0 -1
- package/dist/tracking/spans/otel/fit-row-budget.d.ts +0 -22
- package/dist/tracking/spans/otel/fit-row-budget.d.ts.map +0 -1
- package/dist/tracking/spans/otel/fit-row-budget.js +0 -91
- package/dist/tracking/spans/otel/fit-row-budget.js.map +0 -1
- package/dist/tracking/spans/otel/map-span-to-trace-row.d.ts +0 -16
- package/dist/tracking/spans/otel/map-span-to-trace-row.d.ts.map +0 -1
- package/dist/tracking/spans/otel/map-span-to-trace-row.js +0 -227
- package/dist/tracking/spans/otel/map-span-to-trace-row.js.map +0 -1
- package/dist/tracking/spans/otel/recording-span-transport.d.ts +0 -43
- package/dist/tracking/spans/otel/recording-span-transport.d.ts.map +0 -1
- package/dist/tracking/spans/otel/recording-span-transport.js +0 -67
- package/dist/tracking/spans/otel/recording-span-transport.js.map +0 -1
- package/dist/tracking/spans/otel/span-ids.d.ts +0 -22
- package/dist/tracking/spans/otel/span-ids.d.ts.map +0 -1
- package/dist/tracking/spans/otel/span-ids.js +0 -32
- package/dist/tracking/spans/otel/span-ids.js.map +0 -1
- package/dist/tracking/spans/plugin-span-tracker.d.ts +0 -9
- package/dist/tracking/spans/plugin-span-tracker.d.ts.map +0 -1
- package/dist/tracking/spans/plugin-span-tracker.js +0 -115
- package/dist/tracking/spans/plugin-span-tracker.js.map +0 -1
- package/dist/tracking/spans/span-tracker.d.ts +0 -133
- package/dist/tracking/spans/span-tracker.d.ts.map +0 -1
- package/dist/tracking/spans/span-tracker.js +0 -721
- package/dist/tracking/spans/span-tracker.js.map +0 -1
- package/dist/tracking/spans/span-transport.d.ts +0 -71
- package/dist/tracking/spans/span-transport.d.ts.map +0 -1
- package/dist/tracking/spans/span-transport.js +0 -240
- package/dist/tracking/spans/span-transport.js.map +0 -1
- package/dist/tracking/spans/types.d.ts +0 -101
- package/dist/tracking/spans/types.d.ts.map +0 -1
- package/dist/tracking/spans/types.js +0 -6
- package/dist/tracking/spans/types.js.map +0 -1
|
@@ -1,28 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Span telemetry constants
|
|
2
|
+
* Span telemetry constants.
|
|
3
|
+
*
|
|
4
|
+
* Header names used to cross the runtime → OpenClaw HTTP boundary so the
|
|
5
|
+
* gateway-side hooks can stamp senpi identity onto the gen_ai spans.
|
|
3
6
|
*/
|
|
4
|
-
export const SPANS_API_PATH = "/api/v1/tracking/spans";
|
|
5
|
-
// Transport batching — mirrors the events transport defaults.
|
|
6
|
-
export const FLUSH_INTERVAL_MS = 10_000;
|
|
7
|
-
export const FLUSH_THRESHOLD = 50;
|
|
8
|
-
export const MAX_BUFFER_SIZE = 500;
|
|
9
|
-
// In-memory span lifecycle — sweep abandoned spans so they don't accumulate.
|
|
10
|
-
export const STALE_TIMEOUT_MS = 5 * 60_000;
|
|
11
|
-
export const SWEEP_INTERVAL_MS = 60_000;
|
|
12
|
-
// Per-batch byte budget. We pack spans into a request until adding the next
|
|
13
|
-
// one would push us over this, then flush. Sized to fit comfortably under the
|
|
14
|
-
// ingest server's 10MB Fastify bodyLimit (set in senpi-agent-telemetry).
|
|
15
|
-
export const MAX_BATCH_BYTES = 8_000_000;
|
|
16
|
-
// Per-field byte cap for span.data top-level values. Acts as a safety net for
|
|
17
|
-
// genuinely pathological outputs (e.g. an `exec` that printed a multi-MB log,
|
|
18
|
-
// or a tool that returned a raw binary blob). Real chat-history payloads flow
|
|
19
|
-
// through unchanged after sanitize-payload strips framework metadata.
|
|
20
|
-
// Combined with the ingest server's 10MB body limit, only truly oversized
|
|
21
|
-
// fields trip this.
|
|
22
|
-
export const MAX_SPAN_FIELD_BYTES = 2_000_000;
|
|
23
|
-
/** First N chars of each truncated value retained for debugging context. */
|
|
24
|
-
export const TRUNCATED_PREVIEW_BYTES = 2_000;
|
|
25
|
-
// Header names used to cross the runtime → OpenClaw HTTP boundary.
|
|
26
7
|
export const HEADER_CORRELATION_ID = "x-senpi-correlation-id";
|
|
27
8
|
export const HEADER_ADDRESS = "x-senpi-address";
|
|
28
9
|
export const HEADER_RECIPE_NAME = "x-senpi-recipe-name";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/tracking/spans/constants.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/tracking/spans/constants.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,qBAAqB,GAAG,wBAAwB,CAAC;AAC9D,MAAM,CAAC,MAAM,cAAc,GAAG,iBAAiB,CAAC;AAChD,MAAM,CAAC,MAAM,kBAAkB,GAAG,qBAAqB,CAAC;AACxD,MAAM,CAAC,MAAM,iBAAiB,GAAG,oBAAoB,CAAC;AACtD,MAAM,CAAC,MAAM,sBAAsB,GAAG,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* gen_ai / MCP span mapping — the one place that turns extracted hook content (or on-site
|
|
3
|
+
* MCP call data) into OpenTelemetry GenAI/MCP semantic-convention span attributes (the
|
|
4
|
+
* `GEN_AI` keys below). Standard keys only — no OpenClaw `openclaw.content.*` mirror, no
|
|
5
|
+
* OpenInference `input.value`/`output.value` aliases; `gen_ai.system_instructions` is the
|
|
6
|
+
* spec's underscore form.
|
|
7
|
+
*
|
|
8
|
+
* Content (messages, system instructions, tool args/result) is the highest-PII surface, so
|
|
9
|
+
* it is always redacted *before* stamping and capped *after* (sanitize → redact → cap) so a
|
|
10
|
+
* truncated value can't re-expose a partial secret. If the redactor fails to load, content is
|
|
11
|
+
* dropped rather than emitted unredacted.
|
|
12
|
+
*/
|
|
13
|
+
import type { Attributes, Span } from "@opentelemetry/api";
|
|
14
|
+
/**
|
|
15
|
+
* Max chars per content attribute value, applied after redaction. A transport-safety
|
|
16
|
+
* cap that sits far under the OTLP/HTTP request-body limit (~20 MiB), not a backend
|
|
17
|
+
* storage limit — content this size is rare and we'd rather truncate than risk a
|
|
18
|
+
* rejected export.
|
|
19
|
+
*/
|
|
20
|
+
export declare const MAX_OTEL_CONTENT_ATTRIBUTE_CHARS: number;
|
|
21
|
+
/** Max items per message / tool-definition array, applied after redaction. */
|
|
22
|
+
export declare const MAX_OTEL_CONTENT_ARRAY_ITEMS = 200;
|
|
23
|
+
export declare const GEN_AI: {
|
|
24
|
+
readonly OPERATION_NAME: "gen_ai.operation.name";
|
|
25
|
+
readonly PROVIDER_NAME: "gen_ai.provider.name";
|
|
26
|
+
readonly REQUEST_MODEL: "gen_ai.request.model";
|
|
27
|
+
readonly REQUEST_TEMPERATURE: "gen_ai.request.temperature";
|
|
28
|
+
readonly REQUEST_MAX_TOKENS: "gen_ai.request.max_tokens";
|
|
29
|
+
readonly RESPONSE_MODEL: "gen_ai.response.model";
|
|
30
|
+
readonly RESPONSE_FINISH_REASONS: "gen_ai.response.finish_reasons";
|
|
31
|
+
readonly USAGE_INPUT_TOKENS: "gen_ai.usage.input_tokens";
|
|
32
|
+
readonly USAGE_OUTPUT_TOKENS: "gen_ai.usage.output_tokens";
|
|
33
|
+
readonly SYSTEM_INSTRUCTIONS: "gen_ai.system_instructions";
|
|
34
|
+
readonly INPUT_MESSAGES: "gen_ai.input.messages";
|
|
35
|
+
readonly OUTPUT_MESSAGES: "gen_ai.output.messages";
|
|
36
|
+
readonly TOOL_DEFINITIONS: "gen_ai.tool.definitions";
|
|
37
|
+
readonly AGENT_NAME: "gen_ai.agent.name";
|
|
38
|
+
readonly TOOL_NAME: "gen_ai.tool.name";
|
|
39
|
+
readonly TOOL_CALL_ID: "gen_ai.tool.call.id";
|
|
40
|
+
readonly TOOL_CALL_ARGUMENTS: "gen_ai.tool.call.arguments";
|
|
41
|
+
readonly TOOL_CALL_RESULT: "gen_ai.tool.call.result";
|
|
42
|
+
};
|
|
43
|
+
/** Reset the cached redactor (tests only). */
|
|
44
|
+
export declare function __resetContentRedactorForTest(): void;
|
|
45
|
+
/**
|
|
46
|
+
* Turn a content value into a capped JSON string with PII redacted: sanitize framework
|
|
47
|
+
* metadata, redact (when a redactor is available), then serialize within the caps.
|
|
48
|
+
* Array content keeps the newest items (dropping oldest with a visible elision marker,
|
|
49
|
+
* so the result stays valid JSON); non-array content is tail-truncated with a suffix.
|
|
50
|
+
* Returns `undefined` when the value is empty. Never throws — a failure drops the value.
|
|
51
|
+
*/
|
|
52
|
+
export declare function redactAndCapContent(value: unknown): Promise<string | undefined>;
|
|
53
|
+
/** Redact + cap a content value and stamp it onto the span (when capture is on and non-empty). */
|
|
54
|
+
export declare function setGenAiContentAttribute(span: Span, key: string, value: unknown): Promise<void>;
|
|
55
|
+
/** Set every defined value in `attrs` on the span, skipping undefined/null. Never throws. */
|
|
56
|
+
export declare function setDefinedAttributes(span: Span, attrs: Attributes): void;
|
|
57
|
+
/** Low-cardinality `error.type` for the spec: error.name, the string itself, else "_OTHER". */
|
|
58
|
+
export declare function errorTypeOf(error: unknown): string;
|
|
59
|
+
/**
|
|
60
|
+
* Mark a span as failed: record the exception, set ERROR status, and stamp the spec's
|
|
61
|
+
* low-cardinality `error.type`. Never throws.
|
|
62
|
+
*/
|
|
63
|
+
export declare function recordSpanError(span: Span, error: unknown): void;
|
|
64
|
+
/** First finite number among the candidates, else undefined. */
|
|
65
|
+
export declare function firstNumber(...values: unknown[]): number | undefined;
|
|
66
|
+
/** Normalize a finish-reason value to a string array (gen_ai.response.finish_reasons is an array). */
|
|
67
|
+
export declare function toFinishReasons(value: unknown): string[] | undefined;
|
|
68
|
+
/** Normalize a list of raw provider messages into spec `{ role, parts }` objects. */
|
|
69
|
+
export declare function normalizeGenAiMessages(value: unknown, fallbackRole: "user" | "assistant"): Array<Record<string, unknown>> | undefined;
|
|
70
|
+
//# sourceMappingURL=gen-ai.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gen-ai.d.ts","sourceRoot":"","sources":["../../../src/tracking/spans/gen-ai.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAc3D;;;;;GAKG;AACH,eAAO,MAAM,gCAAgC,QAAa,CAAC;AAC3D,8EAA8E;AAC9E,eAAO,MAAM,4BAA4B,MAAM,CAAC;AAMhD,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;CAmBT,CAAC;AAyBX,8CAA8C;AAC9C,wBAAgB,6BAA6B,IAAI,IAAI,CAEpD;AA+CD;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAyBrF;AAED,kGAAkG;AAClG,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,OAAO,GACb,OAAO,CAAC,IAAI,CAAC,CASf;AAID,6FAA6F;AAC7F,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI,CAQxE;AAED,+FAA+F;AAC/F,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAIlD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAWhE;AAID,gEAAgE;AAChE,wBAAgB,WAAW,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,GAAG,SAAS,CAKpE;AAED,sGAAsG;AACtG,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,GAAG,SAAS,CAQpE;AAgGD,qFAAqF;AACrF,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,OAAO,EACd,YAAY,EAAE,MAAM,GAAG,WAAW,GACjC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,SAAS,CAQ5C"}
|
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* gen_ai / MCP span mapping — the one place that turns extracted hook content (or on-site
|
|
3
|
+
* MCP call data) into OpenTelemetry GenAI/MCP semantic-convention span attributes (the
|
|
4
|
+
* `GEN_AI` keys below). Standard keys only — no OpenClaw `openclaw.content.*` mirror, no
|
|
5
|
+
* OpenInference `input.value`/`output.value` aliases; `gen_ai.system_instructions` is the
|
|
6
|
+
* spec's underscore form.
|
|
7
|
+
*
|
|
8
|
+
* Content (messages, system instructions, tool args/result) is the highest-PII surface, so
|
|
9
|
+
* it is always redacted *before* stamping and capped *after* (sanitize → redact → cap) so a
|
|
10
|
+
* truncated value can't re-expose a partial secret. If the redactor fails to load, content is
|
|
11
|
+
* dropped rather than emitted unredacted.
|
|
12
|
+
*/
|
|
13
|
+
import { SpanStatusCode } from "@opentelemetry/api";
|
|
14
|
+
import { createLogger } from "../../utils/logger.js";
|
|
15
|
+
import { createOpenRedactionAdapter, redactStringsDeep, } from "./redact-pii.js";
|
|
16
|
+
import { sanitizePayloadValue } from "./sanitize-payload.js";
|
|
17
|
+
const logger = createLogger("[senpi-core][gen-ai]");
|
|
18
|
+
// ─── Caps ─────────────────────────────────────────────────────────────────────
|
|
19
|
+
/**
|
|
20
|
+
* Max chars per content attribute value, applied after redaction. A transport-safety
|
|
21
|
+
* cap that sits far under the OTLP/HTTP request-body limit (~20 MiB), not a backend
|
|
22
|
+
* storage limit — content this size is rare and we'd rather truncate than risk a
|
|
23
|
+
* rejected export.
|
|
24
|
+
*/
|
|
25
|
+
export const MAX_OTEL_CONTENT_ATTRIBUTE_CHARS = 256 * 1024;
|
|
26
|
+
/** Max items per message / tool-definition array, applied after redaction. */
|
|
27
|
+
export const MAX_OTEL_CONTENT_ARRAY_ITEMS = 200;
|
|
28
|
+
/** Suffix appended when a non-array (string/object) value is tail-truncated to fit the cap. */
|
|
29
|
+
const TRUNCATION_SUFFIX = "…[truncated]";
|
|
30
|
+
// ─── GenAI semantic-convention attribute keys ────────────────────────────────
|
|
31
|
+
export const GEN_AI = {
|
|
32
|
+
OPERATION_NAME: "gen_ai.operation.name",
|
|
33
|
+
PROVIDER_NAME: "gen_ai.provider.name",
|
|
34
|
+
REQUEST_MODEL: "gen_ai.request.model",
|
|
35
|
+
REQUEST_TEMPERATURE: "gen_ai.request.temperature",
|
|
36
|
+
REQUEST_MAX_TOKENS: "gen_ai.request.max_tokens",
|
|
37
|
+
RESPONSE_MODEL: "gen_ai.response.model",
|
|
38
|
+
RESPONSE_FINISH_REASONS: "gen_ai.response.finish_reasons",
|
|
39
|
+
USAGE_INPUT_TOKENS: "gen_ai.usage.input_tokens",
|
|
40
|
+
USAGE_OUTPUT_TOKENS: "gen_ai.usage.output_tokens",
|
|
41
|
+
SYSTEM_INSTRUCTIONS: "gen_ai.system_instructions",
|
|
42
|
+
INPUT_MESSAGES: "gen_ai.input.messages",
|
|
43
|
+
OUTPUT_MESSAGES: "gen_ai.output.messages",
|
|
44
|
+
TOOL_DEFINITIONS: "gen_ai.tool.definitions",
|
|
45
|
+
AGENT_NAME: "gen_ai.agent.name",
|
|
46
|
+
TOOL_NAME: "gen_ai.tool.name",
|
|
47
|
+
TOOL_CALL_ID: "gen_ai.tool.call.id",
|
|
48
|
+
TOOL_CALL_ARGUMENTS: "gen_ai.tool.call.arguments",
|
|
49
|
+
TOOL_CALL_RESULT: "gen_ai.tool.call.result",
|
|
50
|
+
};
|
|
51
|
+
// ─── Content redactor (always on) ────────────────────────────────────────────
|
|
52
|
+
let redactorPromise = null;
|
|
53
|
+
/**
|
|
54
|
+
* Lazily build (once) the shared content redactor. Cached after first call so the
|
|
55
|
+
* OpenRedaction `enableCache` amortises multi-turn runs. Returns null only if the
|
|
56
|
+
* adapter fails to load (logged once) — callers then drop the content rather than
|
|
57
|
+
* emit it unredacted.
|
|
58
|
+
*/
|
|
59
|
+
async function getContentRedactor() {
|
|
60
|
+
if (redactorPromise === null) {
|
|
61
|
+
redactorPromise = createOpenRedactionAdapter().catch((err) => {
|
|
62
|
+
logger.warn("content redactor init failed; gen_ai content will be dropped until restart", err instanceof Error ? err : new Error(String(err)));
|
|
63
|
+
return null;
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
return redactorPromise;
|
|
67
|
+
}
|
|
68
|
+
/** Reset the cached redactor (tests only). */
|
|
69
|
+
export function __resetContentRedactorForTest() {
|
|
70
|
+
redactorPromise = null;
|
|
71
|
+
}
|
|
72
|
+
// ─── Redact → cap → serialize ────────────────────────────────────────────────
|
|
73
|
+
/** Build the elision marker prepended when older array elements are dropped. */
|
|
74
|
+
function elisionMarker(droppedCount) {
|
|
75
|
+
return {
|
|
76
|
+
role: "system",
|
|
77
|
+
parts: [{ type: "text", content: `[${droppedCount} earlier messages elided]` }],
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Cap an array (e.g. message history) keeping the NEWEST content. Trims the item count
|
|
82
|
+
* to the last {@link MAX_OTEL_CONTENT_ARRAY_ITEMS}, then — when the serialized JSON still
|
|
83
|
+
* exceeds the char cap — drops whole elements from the front (oldest) until it fits,
|
|
84
|
+
* prepending a single elision marker so the gap is visible. Returns the serialized string.
|
|
85
|
+
*/
|
|
86
|
+
function serializeArrayWithCap(value) {
|
|
87
|
+
let items = value.length > MAX_OTEL_CONTENT_ARRAY_ITEMS
|
|
88
|
+
? value.slice(value.length - MAX_OTEL_CONTENT_ARRAY_ITEMS)
|
|
89
|
+
: value.slice();
|
|
90
|
+
const itemsTrimmed = value.length - items.length;
|
|
91
|
+
let dropped = 0;
|
|
92
|
+
let serialized = JSON.stringify(items);
|
|
93
|
+
while (serialized.length > MAX_OTEL_CONTENT_ATTRIBUTE_CHARS && items.length > 0) {
|
|
94
|
+
items.shift();
|
|
95
|
+
dropped += 1;
|
|
96
|
+
serialized = JSON.stringify([elisionMarker(itemsTrimmed + dropped), ...items]);
|
|
97
|
+
}
|
|
98
|
+
if (dropped > 0)
|
|
99
|
+
return serialized;
|
|
100
|
+
if (itemsTrimmed > 0)
|
|
101
|
+
return JSON.stringify([elisionMarker(itemsTrimmed), ...items]);
|
|
102
|
+
return serialized;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Tail-truncate a non-array serialized string to the char cap and append a compact
|
|
106
|
+
* suffix. Acceptable for non-cumulative values (system instructions, tool args/result)
|
|
107
|
+
* where the attribute is a plain string, not history we need to keep parseable.
|
|
108
|
+
*/
|
|
109
|
+
function capString(serialized) {
|
|
110
|
+
if (serialized.length <= MAX_OTEL_CONTENT_ATTRIBUTE_CHARS)
|
|
111
|
+
return serialized;
|
|
112
|
+
const keep = MAX_OTEL_CONTENT_ATTRIBUTE_CHARS - TRUNCATION_SUFFIX.length;
|
|
113
|
+
return serialized.slice(0, Math.max(0, keep)) + TRUNCATION_SUFFIX;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Turn a content value into a capped JSON string with PII redacted: sanitize framework
|
|
117
|
+
* metadata, redact (when a redactor is available), then serialize within the caps.
|
|
118
|
+
* Array content keeps the newest items (dropping oldest with a visible elision marker,
|
|
119
|
+
* so the result stays valid JSON); non-array content is tail-truncated with a suffix.
|
|
120
|
+
* Returns `undefined` when the value is empty. Never throws — a failure drops the value.
|
|
121
|
+
*/
|
|
122
|
+
export async function redactAndCapContent(value) {
|
|
123
|
+
if (value === undefined || value === null)
|
|
124
|
+
return undefined;
|
|
125
|
+
try {
|
|
126
|
+
const sanitized = sanitizePayloadValue(value);
|
|
127
|
+
const redactor = await getContentRedactor();
|
|
128
|
+
// Fail closed: if the redactor didn't load, drop the content rather than emit it
|
|
129
|
+
// unredacted — it is the highest-PII surface.
|
|
130
|
+
if (!redactor)
|
|
131
|
+
return undefined;
|
|
132
|
+
const redacted = await redactStringsDeep(sanitized, redactor);
|
|
133
|
+
if (typeof redacted === "string") {
|
|
134
|
+
return redacted.length === 0 ? undefined : capString(redacted);
|
|
135
|
+
}
|
|
136
|
+
if (Array.isArray(redacted)) {
|
|
137
|
+
const serialized = serializeArrayWithCap(redacted);
|
|
138
|
+
return serialized.length === 0 ? undefined : serialized;
|
|
139
|
+
}
|
|
140
|
+
const serialized = JSON.stringify(redacted);
|
|
141
|
+
if (serialized === undefined || serialized.length === 0)
|
|
142
|
+
return undefined;
|
|
143
|
+
return capString(serialized);
|
|
144
|
+
}
|
|
145
|
+
catch (err) {
|
|
146
|
+
logger.warn("failed to redact/serialize gen_ai content; dropping value", {
|
|
147
|
+
err: err instanceof Error ? err.message : String(err),
|
|
148
|
+
});
|
|
149
|
+
return undefined;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/** Redact + cap a content value and stamp it onto the span (when capture is on and non-empty). */
|
|
153
|
+
export async function setGenAiContentAttribute(span, key, value) {
|
|
154
|
+
const out = await redactAndCapContent(value);
|
|
155
|
+
if (out !== undefined) {
|
|
156
|
+
try {
|
|
157
|
+
span.setAttribute(key, out);
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
// Tracing must never break the caller.
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// ─── Metadata helpers ────────────────────────────────────────────────────────
|
|
165
|
+
/** Set every defined value in `attrs` on the span, skipping undefined/null. Never throws. */
|
|
166
|
+
export function setDefinedAttributes(span, attrs) {
|
|
167
|
+
try {
|
|
168
|
+
for (const [k, v] of Object.entries(attrs)) {
|
|
169
|
+
if (v !== undefined && v !== null)
|
|
170
|
+
span.setAttribute(k, v);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
// Tracing must never break the caller.
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/** Low-cardinality `error.type` for the spec: error.name, the string itself, else "_OTHER". */
|
|
178
|
+
export function errorTypeOf(error) {
|
|
179
|
+
if (error instanceof Error)
|
|
180
|
+
return error.name;
|
|
181
|
+
if (typeof error === "string")
|
|
182
|
+
return error;
|
|
183
|
+
return "_OTHER";
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Mark a span as failed: record the exception, set ERROR status, and stamp the spec's
|
|
187
|
+
* low-cardinality `error.type`. Never throws.
|
|
188
|
+
*/
|
|
189
|
+
export function recordSpanError(span, error) {
|
|
190
|
+
try {
|
|
191
|
+
span.recordException(error instanceof Error ? error : { message: String(error) });
|
|
192
|
+
span.setStatus({
|
|
193
|
+
code: SpanStatusCode.ERROR,
|
|
194
|
+
message: error instanceof Error ? error.message : String(error),
|
|
195
|
+
});
|
|
196
|
+
span.setAttribute("error.type", errorTypeOf(error));
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
// Tracing must never break the caller.
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
// ─── Value coercion ──────────────────────────────────────────────────────────
|
|
203
|
+
/** First finite number among the candidates, else undefined. */
|
|
204
|
+
export function firstNumber(...values) {
|
|
205
|
+
for (const v of values) {
|
|
206
|
+
if (typeof v === "number" && Number.isFinite(v))
|
|
207
|
+
return v;
|
|
208
|
+
}
|
|
209
|
+
return undefined;
|
|
210
|
+
}
|
|
211
|
+
/** Normalize a finish-reason value to a string array (gen_ai.response.finish_reasons is an array). */
|
|
212
|
+
export function toFinishReasons(value) {
|
|
213
|
+
if (value === undefined || value === null)
|
|
214
|
+
return undefined;
|
|
215
|
+
if (Array.isArray(value)) {
|
|
216
|
+
const out = value.filter((v) => typeof v === "string");
|
|
217
|
+
return out.length > 0 ? out : undefined;
|
|
218
|
+
}
|
|
219
|
+
if (typeof value === "string" && value.length > 0)
|
|
220
|
+
return [value];
|
|
221
|
+
return undefined;
|
|
222
|
+
}
|
|
223
|
+
// ─── gen_ai message normalization ─────────────────────────────────────────────
|
|
224
|
+
// Shape input/output messages into the spec's `{ role, parts: [...] }` structure
|
|
225
|
+
// (parts are typed: text / tool_call / tool_call_response), matching the native
|
|
226
|
+
// gateway mapping so the gen_ai views render identically. Unknown content is kept
|
|
227
|
+
// as a native nested object (not stringified) rather than dropped, so the single
|
|
228
|
+
// outer serialize escapes it exactly once.
|
|
229
|
+
function isRecord(v) {
|
|
230
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
231
|
+
}
|
|
232
|
+
function textPart(content) {
|
|
233
|
+
return { type: "text", content };
|
|
234
|
+
}
|
|
235
|
+
function toolCallResponsePart(part) {
|
|
236
|
+
return {
|
|
237
|
+
type: "tool_call_response",
|
|
238
|
+
...(typeof part.id === "string" ? { id: part.id } : {}),
|
|
239
|
+
result: part.result ?? part.response ?? part.content ?? "",
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
/** Turn a message's `content` (string, array of blocks, or object) into typed parts. */
|
|
243
|
+
function contentParts(value) {
|
|
244
|
+
if (typeof value === "string")
|
|
245
|
+
return value.length > 0 ? [textPart(value)] : [];
|
|
246
|
+
if (!Array.isArray(value)) {
|
|
247
|
+
if (value === undefined || value === null)
|
|
248
|
+
return [];
|
|
249
|
+
// Keep an unknown object as a native nested part — the single outer
|
|
250
|
+
// JSON.stringify in redactAndCapContent serializes it exactly once
|
|
251
|
+
// (pre-stringifying here would double-escape its sub-structures).
|
|
252
|
+
if (isRecord(value))
|
|
253
|
+
return [value];
|
|
254
|
+
return [textPart(String(value))];
|
|
255
|
+
}
|
|
256
|
+
const parts = [];
|
|
257
|
+
for (const part of value) {
|
|
258
|
+
if (typeof part === "string") {
|
|
259
|
+
if (part.length > 0)
|
|
260
|
+
parts.push(textPart(part));
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
if (!isRecord(part))
|
|
264
|
+
continue;
|
|
265
|
+
if (typeof part.text === "string") {
|
|
266
|
+
parts.push(textPart(part.text));
|
|
267
|
+
}
|
|
268
|
+
else if (part.type === "text" && typeof part.content === "string") {
|
|
269
|
+
parts.push(textPart(part.content));
|
|
270
|
+
}
|
|
271
|
+
else if ((part.type === "tool_call" || part.type === "toolCall") && typeof part.name === "string") {
|
|
272
|
+
parts.push({
|
|
273
|
+
type: "tool_call",
|
|
274
|
+
name: part.name,
|
|
275
|
+
...(typeof part.id === "string" ? { id: part.id } : {}),
|
|
276
|
+
...(part.arguments !== undefined ? { arguments: part.arguments } : {}),
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
else if (part.type === "tool_call_response") {
|
|
280
|
+
parts.push(toolCallResponsePart(part));
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
// Unknown part kept as a native nested object (not stringified) so the
|
|
284
|
+
// single outer JSON.stringify serializes it once — preserving its real
|
|
285
|
+
// fields rather than escaping them into a text blob.
|
|
286
|
+
parts.push(part);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
return parts;
|
|
290
|
+
}
|
|
291
|
+
function normalizeGenAiMessage(value, fallbackRole) {
|
|
292
|
+
if (typeof value === "string") {
|
|
293
|
+
return value.length > 0 ? { role: fallbackRole, parts: [textPart(value)] } : undefined;
|
|
294
|
+
}
|
|
295
|
+
if (!isRecord(value))
|
|
296
|
+
return undefined;
|
|
297
|
+
const rawRole = typeof value.role === "string" ? value.role : fallbackRole;
|
|
298
|
+
const role = rawRole === "toolResult" ? "tool" : rawRole;
|
|
299
|
+
let parts;
|
|
300
|
+
if (role === "tool") {
|
|
301
|
+
const explicit = contentParts(value.parts);
|
|
302
|
+
parts =
|
|
303
|
+
explicit.length > 0
|
|
304
|
+
? explicit
|
|
305
|
+
: [toolCallResponsePart({ id: value.toolCallId, result: value.content ?? "" })];
|
|
306
|
+
}
|
|
307
|
+
else {
|
|
308
|
+
parts = contentParts(value.parts ?? value.content);
|
|
309
|
+
}
|
|
310
|
+
if (parts.length === 0)
|
|
311
|
+
return undefined;
|
|
312
|
+
const finish = typeof value.finish_reason === "string"
|
|
313
|
+
? value.finish_reason
|
|
314
|
+
: typeof value.stopReason === "string"
|
|
315
|
+
? value.stopReason
|
|
316
|
+
: undefined;
|
|
317
|
+
return { role, parts, ...(finish ? { finish_reason: finish } : {}) };
|
|
318
|
+
}
|
|
319
|
+
/** Normalize a list of raw provider messages into spec `{ role, parts }` objects. */
|
|
320
|
+
export function normalizeGenAiMessages(value, fallbackRole) {
|
|
321
|
+
const source = Array.isArray(value) ? value : value === undefined || value === null ? [] : [value];
|
|
322
|
+
const out = [];
|
|
323
|
+
for (const item of source) {
|
|
324
|
+
const msg = normalizeGenAiMessage(item, fallbackRole);
|
|
325
|
+
if (msg)
|
|
326
|
+
out.push(msg);
|
|
327
|
+
}
|
|
328
|
+
return out.length > 0 ? out : undefined;
|
|
329
|
+
}
|
|
330
|
+
//# sourceMappingURL=gen-ai.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gen-ai.js","sourceRoot":"","sources":["../../../src/tracking/spans/gen-ai.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Span telemetry — barrel export.
|
|
3
|
+
*
|
|
4
|
+
* Agent telemetry (LLM / tool / subagent / MCP) is emitted as real OTel gen_ai spans
|
|
5
|
+
* through the shared tracer: the gateway hooks via {@link registerSpanHooks}, on-site
|
|
6
|
+
* MCP calls via `SenpiClient.callTool` (both using the {@link module:gen-ai} mapping).
|
|
3
7
|
*/
|
|
4
|
-
export
|
|
5
|
-
export { SPANS_API_PATH, HEADER_CORRELATION_ID, HEADER_ADDRESS, HEADER_RECIPE_NAME, HEADER_RUNTIME_ID, HEADER_RUNTIME_VERSION, } from "./constants.js";
|
|
6
|
-
export { BatchingSpanTransport, NoOpSpanTransport, type BatchingSpanTransportOptions, } from "./span-transport.js";
|
|
7
|
-
export { SpanTracker, type AgentEndInput, type DirectLlmSpanInput, type DirectToolSpanInput, type FinalizeLlmSpanInput, type FinalizeSubagentInput, type FinalizeToolSpanInput, type MergeSubagentInput, type OpenLlmSpanInput, type OpenSubagentInput, type OpenToolSpanInput, type SpanContextFields, type SpanTrackerOptions, } from "./span-tracker.js";
|
|
8
|
+
export { HEADER_CORRELATION_ID, HEADER_ADDRESS, HEADER_RECIPE_NAME, HEADER_RUNTIME_ID, HEADER_RUNTIME_VERSION, } from "./constants.js";
|
|
8
9
|
export { registerSpanHooks, type RegisterSpanHooksOptions, type SpanHooksPluginApi, } from "./span-hooks.js";
|
|
9
|
-
export {
|
|
10
|
-
import type { SpanTracker as _SpanTracker } from "./span-tracker.js";
|
|
11
|
-
export declare function setDefaultSpanTracker(tracker: _SpanTracker | null): void;
|
|
12
|
-
export declare function getDefaultSpanTracker(): _SpanTracker | null;
|
|
10
|
+
export { GEN_AI, setGenAiContentAttribute, redactAndCapContent, } from "./gen-ai.js";
|
|
13
11
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tracking/spans/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tracking/spans/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,qBAAqB,EACrB,cAAc,EACd,kBAAkB,EAClB,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,iBAAiB,EACjB,KAAK,wBAAwB,EAC7B,KAAK,kBAAkB,GACxB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,MAAM,EACN,wBAAwB,EACxB,mBAAmB,GACpB,MAAM,aAAa,CAAC"}
|
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Span telemetry — barrel export.
|
|
3
|
+
*
|
|
4
|
+
* Agent telemetry (LLM / tool / subagent / MCP) is emitted as real OTel gen_ai spans
|
|
5
|
+
* through the shared tracer: the gateway hooks via {@link registerSpanHooks}, on-site
|
|
6
|
+
* MCP calls via `SenpiClient.callTool` (both using the {@link module:gen-ai} mapping).
|
|
3
7
|
*/
|
|
4
|
-
export {
|
|
5
|
-
export { BatchingSpanTransport, NoOpSpanTransport, } from "./span-transport.js";
|
|
6
|
-
export { SpanTracker, } from "./span-tracker.js";
|
|
8
|
+
export { HEADER_CORRELATION_ID, HEADER_ADDRESS, HEADER_RECIPE_NAME, HEADER_RUNTIME_ID, HEADER_RUNTIME_VERSION, } from "./constants.js";
|
|
7
9
|
export { registerSpanHooks, } from "./span-hooks.js";
|
|
8
|
-
export {
|
|
9
|
-
let defaultSpanTracker = null;
|
|
10
|
-
export function setDefaultSpanTracker(tracker) {
|
|
11
|
-
defaultSpanTracker = tracker;
|
|
12
|
-
}
|
|
13
|
-
export function getDefaultSpanTracker() {
|
|
14
|
-
return defaultSpanTracker;
|
|
15
|
-
}
|
|
10
|
+
export { GEN_AI, setGenAiContentAttribute, redactAndCapContent, } from "./gen-ai.js";
|
|
16
11
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tracking/spans/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tracking/spans/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,qBAAqB,EACrB,cAAc,EACd,kBAAkB,EAClB,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,iBAAiB,GAGlB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,MAAM,EACN,wBAAwB,EACxB,mBAAmB,GACpB,MAAM,aAAa,CAAC"}
|
|
@@ -1,26 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* PII + secret redaction for span
|
|
2
|
+
* PII + secret redaction for span content.
|
|
3
3
|
*
|
|
4
|
-
* Walks
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* latency on the network-bound path rather than on the caller's enqueue call.
|
|
4
|
+
* Walks a JSON-shaped value and replaces matches in string values. Reused by the
|
|
5
|
+
* gen_ai content path (`gen-ai.ts`), which redacts conversation/tool content inline
|
|
6
|
+
* before stamping it onto a span (awaited per call).
|
|
8
7
|
*
|
|
9
8
|
* Scope (see createOpenRedactionAdapter): emails, phones (US, international,
|
|
10
9
|
* India, China, South Korea, Japan, UK mobile, Brazil), ~28 vendor API keys
|
|
11
10
|
* / tokens (AWS, GitHub, Stripe, OpenAI, etc.), EVM private keys, Anthropic
|
|
12
11
|
* `sk-ant-*` keys, generic `sk-*` keys, and BIP39 mnemonic phrases.
|
|
13
12
|
*
|
|
14
|
-
* Integration point: BatchingSpanTransport.flush() applies this to every
|
|
15
|
-
* span in the batch before JSON.stringify. Only `span.data` is walked;
|
|
16
|
-
* top-level columns (`address`, `correlationId`, etc.) are non-PII identifiers
|
|
17
|
-
* and stay as-is.
|
|
18
|
-
*
|
|
19
13
|
* The process-wide default redactor is registered unconditionally at plugin
|
|
20
|
-
* boot (see
|
|
21
|
-
*
|
|
14
|
+
* boot (see initDefaultPiiRedactor), so the event-log redact-field path
|
|
15
|
+
* (`logger.event()`) is scrubbed without an env gate.
|
|
22
16
|
*/
|
|
23
|
-
import type { TrackingSpan } from "./types.js";
|
|
24
17
|
/** Minimal interface so tests can inject a synchronous stub. */
|
|
25
18
|
export interface PiiRedactor {
|
|
26
19
|
redact(text: string): Promise<string>;
|
|
@@ -32,16 +25,21 @@ export interface PiiRedactor {
|
|
|
32
25
|
* when nothing changes — useful for short-circuit downstream comparisons.
|
|
33
26
|
*/
|
|
34
27
|
export declare function redactStringsDeep(value: unknown, redactor: PiiRedactor): Promise<unknown>;
|
|
28
|
+
export declare function setDefaultPiiRedactor(r: PiiRedactor | null): void;
|
|
29
|
+
export declare function getDefaultPiiRedactor(): PiiRedactor | null;
|
|
35
30
|
/**
|
|
36
|
-
*
|
|
37
|
-
*
|
|
31
|
+
* Register the process-wide default PII redactor at plugin boot. Always on, no
|
|
32
|
+
* env gate: `logger.event()` redact fields (free-text LLM reasoning, venue
|
|
33
|
+
* errors, raw signals) are scrubbed on the live path.
|
|
38
34
|
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
35
|
+
* Fire-and-forget and never awaited, so it adds no boot latency and can't
|
|
36
|
+
* introduce a boot failure mode. The OpenRedaction + bip39 imports are dynamic,
|
|
37
|
+
* so they cold-start here; until the promise resolves `getDefaultPiiRedactor()`
|
|
38
|
+
* is null and the event path fails safe (drops the fields rather than emitting
|
|
39
|
+
* them raw). On install failure the redactor stays null — the fields keep being
|
|
40
|
+
* dropped, never leaked.
|
|
41
41
|
*/
|
|
42
|
-
export declare function
|
|
43
|
-
export declare function setDefaultPiiRedactor(r: PiiRedactor | null): void;
|
|
44
|
-
export declare function getDefaultPiiRedactor(): PiiRedactor | null;
|
|
42
|
+
export declare function initDefaultPiiRedactor(): void;
|
|
45
43
|
/**
|
|
46
44
|
* Find BIP39-mnemonic spans in `text` using a true sliding window — not
|
|
47
45
|
* a greedy regex with a post-hoc validator.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redact-pii.d.ts","sourceRoot":"","sources":["../../../src/tracking/spans/redact-pii.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"redact-pii.d.ts","sourceRoot":"","sources":["../../../src/tracking/spans/redact-pii.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAMH,gEAAgE;AAChE,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACvC;AAQD;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,WAAW,GACpB,OAAO,CAAC,OAAO,CAAC,CAgClB;AAUD,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,WAAW,GAAG,IAAI,GAAG,IAAI,CAEjE;AAED,wBAAgB,qBAAqB,IAAI,WAAW,GAAG,IAAI,CAE1D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,CAc7C;AAqOD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,GACjB,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CA0CvC;AAsBD;;;;GAIG;AACH,wBAAsB,2BAA2B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAI/E;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAsB,0BAA0B,IAAI,OAAO,CAAC,WAAW,CAAC,CAkCvE"}
|