@graphorin/observability 0.5.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/CHANGELOG.md +7 -0
- package/LICENSE +21 -0
- package/README.md +115 -0
- package/dist/cost/cost-tracker.d.ts +28 -0
- package/dist/cost/cost-tracker.d.ts.map +1 -0
- package/dist/cost/cost-tracker.js +169 -0
- package/dist/cost/cost-tracker.js.map +1 -0
- package/dist/cost/index.d.ts +3 -0
- package/dist/cost/index.js +3 -0
- package/dist/cost/types.d.ts +104 -0
- package/dist/cost/types.d.ts.map +1 -0
- package/dist/eval/index.d.ts +3 -0
- package/dist/eval/index.js +3 -0
- package/dist/eval/runner.d.ts +11 -0
- package/dist/eval/runner.d.ts.map +1 -0
- package/dist/eval/runner.js +113 -0
- package/dist/eval/runner.js.map +1 -0
- package/dist/eval/types.d.ts +108 -0
- package/dist/eval/types.d.ts.map +1 -0
- package/dist/exporters/console.d.ts +27 -0
- package/dist/exporters/console.d.ts.map +1 -0
- package/dist/exporters/console.js +47 -0
- package/dist/exporters/console.js.map +1 -0
- package/dist/exporters/index.d.ts +6 -0
- package/dist/exporters/index.js +7 -0
- package/dist/exporters/jsonl.d.ts +57 -0
- package/dist/exporters/jsonl.d.ts.map +1 -0
- package/dist/exporters/jsonl.js +95 -0
- package/dist/exporters/jsonl.js.map +1 -0
- package/dist/exporters/otlp-http.d.ts +38 -0
- package/dist/exporters/otlp-http.d.ts.map +1 -0
- package/dist/exporters/otlp-http.js +115 -0
- package/dist/exporters/otlp-http.js.map +1 -0
- package/dist/exporters/types.d.ts +72 -0
- package/dist/exporters/types.d.ts.map +1 -0
- package/dist/exporters/types.js +13 -0
- package/dist/exporters/types.js.map +1 -0
- package/dist/exporters/with-validation.d.ts +45 -0
- package/dist/exporters/with-validation.d.ts.map +1 -0
- package/dist/exporters/with-validation.js +99 -0
- package/dist/exporters/with-validation.js.map +1 -0
- package/dist/gen-ai/emit.d.ts +27 -0
- package/dist/gen-ai/emit.d.ts.map +1 -0
- package/dist/gen-ai/emit.js +88 -0
- package/dist/gen-ai/emit.js.map +1 -0
- package/dist/gen-ai/index.d.ts +5 -0
- package/dist/gen-ai/index.js +5 -0
- package/dist/gen-ai/operation-mapping.d.ts +24 -0
- package/dist/gen-ai/operation-mapping.d.ts.map +1 -0
- package/dist/gen-ai/operation-mapping.js +67 -0
- package/dist/gen-ai/operation-mapping.js.map +1 -0
- package/dist/gen-ai/system-derivation.d.ts +41 -0
- package/dist/gen-ai/system-derivation.d.ts.map +1 -0
- package/dist/gen-ai/system-derivation.js +67 -0
- package/dist/gen-ai/system-derivation.js.map +1 -0
- package/dist/gen-ai/types.d.ts +87 -0
- package/dist/gen-ai/types.d.ts.map +1 -0
- package/dist/index.d.ts +58 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +60 -0
- package/dist/index.js.map +1 -0
- package/dist/logger/index.d.ts +2 -0
- package/dist/logger/index.js +3 -0
- package/dist/logger/logger.d.ts +53 -0
- package/dist/logger/logger.d.ts.map +1 -0
- package/dist/logger/logger.js +145 -0
- package/dist/logger/logger.js.map +1 -0
- package/dist/openinference/index.d.ts +45 -0
- package/dist/openinference/index.d.ts.map +1 -0
- package/dist/openinference/index.js +92 -0
- package/dist/openinference/index.js.map +1 -0
- package/dist/redaction/config.d.ts +39 -0
- package/dist/redaction/config.d.ts.map +1 -0
- package/dist/redaction/config.js +15 -0
- package/dist/redaction/config.js.map +1 -0
- package/dist/redaction/errors.d.ts +36 -0
- package/dist/redaction/errors.d.ts.map +1 -0
- package/dist/redaction/errors.js +42 -0
- package/dist/redaction/errors.js.map +1 -0
- package/dist/redaction/imperative-patterns.d.ts +108 -0
- package/dist/redaction/imperative-patterns.d.ts.map +1 -0
- package/dist/redaction/imperative-patterns.js +187 -0
- package/dist/redaction/imperative-patterns.js.map +1 -0
- package/dist/redaction/index.d.ts +7 -0
- package/dist/redaction/index.js +7 -0
- package/dist/redaction/patterns.d.ts +85 -0
- package/dist/redaction/patterns.d.ts.map +1 -0
- package/dist/redaction/patterns.js +172 -0
- package/dist/redaction/patterns.js.map +1 -0
- package/dist/redaction/types.d.ts +103 -0
- package/dist/redaction/types.d.ts.map +1 -0
- package/dist/redaction/validator.d.ts +26 -0
- package/dist/redaction/validator.d.ts.map +1 -0
- package/dist/redaction/validator.js +195 -0
- package/dist/redaction/validator.js.map +1 -0
- package/dist/replay/config.d.ts +56 -0
- package/dist/replay/config.d.ts.map +1 -0
- package/dist/replay/config.js +18 -0
- package/dist/replay/config.js.map +1 -0
- package/dist/replay/index.d.ts +5 -0
- package/dist/replay/index.js +5 -0
- package/dist/replay/log.d.ts +39 -0
- package/dist/replay/log.d.ts.map +1 -0
- package/dist/replay/log.js +59 -0
- package/dist/replay/log.js.map +1 -0
- package/dist/replay/replay.d.ts +25 -0
- package/dist/replay/replay.d.ts.map +1 -0
- package/dist/replay/replay.js +173 -0
- package/dist/replay/replay.js.map +1 -0
- package/dist/replay/types.d.ts +110 -0
- package/dist/replay/types.d.ts.map +1 -0
- package/dist/telemetry/index.d.ts +63 -0
- package/dist/telemetry/index.d.ts.map +1 -0
- package/dist/telemetry/index.js +49 -0
- package/dist/telemetry/index.js.map +1 -0
- package/dist/tracer/ids.d.ts +23 -0
- package/dist/tracer/ids.d.ts.map +1 -0
- package/dist/tracer/ids.js +30 -0
- package/dist/tracer/ids.js.map +1 -0
- package/dist/tracer/index.d.ts +6 -0
- package/dist/tracer/index.js +6 -0
- package/dist/tracer/sampling.d.ts +77 -0
- package/dist/tracer/sampling.d.ts.map +1 -0
- package/dist/tracer/sampling.js +67 -0
- package/dist/tracer/sampling.js.map +1 -0
- package/dist/tracer/span-names.d.ts +11 -0
- package/dist/tracer/span-names.d.ts.map +1 -0
- package/dist/tracer/span-names.js +11 -0
- package/dist/tracer/span-names.js.map +1 -0
- package/dist/tracer/span.d.ts +27 -0
- package/dist/tracer/span.d.ts.map +1 -0
- package/dist/tracer/span.js +80 -0
- package/dist/tracer/span.js.map +1 -0
- package/dist/tracer/tracer.d.ts +101 -0
- package/dist/tracer/tracer.d.ts.map +1 -0
- package/dist/tracer/tracer.js +150 -0
- package/dist/tracer/tracer.js.map +1 -0
- package/package.json +138 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":[],"sources":["../../src/gen-ai/types.ts"],"sourcesContent":[],"mappings":";;;;AA2FA;AAqBA;;;;;AAamC,KA9GvB,WAAA,GA8GuB,WAAA,GAAA,QAAA,GAAA,QAAA,GAAA,SAAA,GAAA,QAAA,GAAA,YAAA,GAAA,oBAAA,GAAA,aAAA,GAAA,QAAA,GAAA,WAAA,GAAA,oBAAA,GAAA,6BAAA,GAAA,CAAA,MAAA,GAAA;EAavB,SAAA,aAAA,CAAA,EAAA,KAAuB;;;;;;;;KAtGvB,aAAA;;;;;;;KAcA,kBAAA;;;;;;KAkCA,gBAAA;;;;;;UAOK,YAAA;iBACA;;;uBAGM;;;;;;;;;;;;;;;;UAiBN,eAAA;oBACG;;;;;;2BAMO;uBACJ;;;;;sBAKD;;;;;;;;;;;;KAaV,uBAAA,UAAiC,aAAa"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { CostBudgetExceededCallback, CostBudgets, CostRecordInput, CostScope, CostSnapshot, CostTrackerOptions } from "./cost/types.js";
|
|
2
|
+
import { CostTracker, createCostTracker } from "./cost/cost-tracker.js";
|
|
3
|
+
import { Case, Dataset, EvalCaseResult, EvalReport, RunEvalOptions, ScoreResult, Scorer } from "./eval/types.js";
|
|
4
|
+
import { runEval } from "./eval/runner.js";
|
|
5
|
+
import { SpanRecord, SpanRecordEvent, TraceExporter, VALIDATED_EXPORTER_BRAND } from "./exporters/types.js";
|
|
6
|
+
import { ConsoleExporterOptions, createConsoleExporter } from "./exporters/console.js";
|
|
7
|
+
import { JSONLExporterOptions, createJSONLExporter } from "./exporters/jsonl.js";
|
|
8
|
+
import { OTLPHttpExporterOptions, createOTLPHttpExporter } from "./exporters/otlp-http.js";
|
|
9
|
+
import { ALL_BUILT_IN_PATTERNS, BUILT_IN_PATTERNS, BuiltInPatternName, OPT_IN_PATTERNS, PatternCategory, RedactionPattern } from "./redaction/patterns.js";
|
|
10
|
+
import { RedactionCounters, RedactionInput, RedactionOutput, RedactionValidator, RedactionValidatorInstance, RedactionValidatorOptions, RedactionViolation, RedactionViolationCallback } from "./redaction/types.js";
|
|
11
|
+
import { WithValidationOptions, isValidatedExporter, tryGetValidatorCounters, withValidation } from "./exporters/with-validation.js";
|
|
12
|
+
import { GenAIAttributes, GenAIMessage, GenAIMessageRole, GenAIOperationName, GenAISystem, GenAIToolType, SpanTypeToOperationName } from "./gen-ai/types.js";
|
|
13
|
+
import { emitGenAIAttributes, emitGenAIMessageEvents } from "./gen-ai/emit.js";
|
|
14
|
+
import { OPERATION_NAME_TABLE, operationNameFor } from "./gen-ai/operation-mapping.js";
|
|
15
|
+
import { PROVIDER_CLASS_TO_GEN_AI_SYSTEM, _resetGenAISystemWarningsForTesting, deriveGenAISystem, setGenAISystemWarnSink } from "./gen-ai/system-derivation.js";
|
|
16
|
+
import { LoggerFormat, LoggerOptions, createLogger, getCurrentSpanContext, withCurrentSpan } from "./logger/logger.js";
|
|
17
|
+
import { OPEN_INFERENCE_EXCLUDED_TYPES, OPEN_INFERENCE_KIND_TABLE, OpenInferenceSpanKind, emitOpenInferenceKind, openInferenceKindFor } from "./openinference/index.js";
|
|
18
|
+
import { DEFAULT_VALIDATION_CONFIG, ValidationConfig } from "./redaction/config.js";
|
|
19
|
+
import { RedactionValidationError, UnvalidatedExporterError } from "./redaction/errors.js";
|
|
20
|
+
import { BUILT_IN_IMPERATIVE_PATTERNS, IMPERATIVE_PREFILTER_SUBSTRINGS, ImperativePattern, ImperativePatternName, ScanResult, scanImperativePatterns, stripImperativePatterns } from "./redaction/imperative-patterns.js";
|
|
21
|
+
import { compareSensitivityTiers, createRedactionValidator } from "./redaction/validator.js";
|
|
22
|
+
import { DEFAULT_REPLAY_LOG_CONFIG, ReplayLogConfig } from "./replay/config.js";
|
|
23
|
+
import { PruneTracesOptions, getTraceLog, pruneTraces } from "./replay/log.js";
|
|
24
|
+
import { ReplayAuditBridge, ReplayAuditEvent, ReplayEvent, ReplayMode, ReplayOptions, ReplayRunInput } from "./replay/types.js";
|
|
25
|
+
import { Replay, createReplay } from "./replay/replay.js";
|
|
26
|
+
import { TelemetryStatus, announceTelemetryPosture, enableTelemetry, getTelemetryStatus } from "./telemetry/index.js";
|
|
27
|
+
import { newSpanId, newTraceId } from "./tracer/ids.js";
|
|
28
|
+
import { Sampler, SamplingDecisionMaker, SamplingOptions, SamplingRule, createSampler } from "./tracer/sampling.js";
|
|
29
|
+
import { GraphorinSpan, SetAttributeOptions } from "./tracer/span.js";
|
|
30
|
+
import { spanNameFor } from "./tracer/span-names.js";
|
|
31
|
+
import { GraphorinTracer, TracerOptions, asGraphorinSpan, createTracer } from "./tracer/tracer.js";
|
|
32
|
+
|
|
33
|
+
//#region src/index.d.ts
|
|
34
|
+
/**
|
|
35
|
+
* @graphorin/observability — observability primitives for the
|
|
36
|
+
* Graphorin framework. Ships:
|
|
37
|
+
*
|
|
38
|
+
* - the typed `AISpan<T>` tracer over OpenTelemetry,
|
|
39
|
+
* - the **mandatory** `withValidation()` wrapper for every exporter,
|
|
40
|
+
* - the sensitivity-aware `RedactionValidator` with 14 built-in PII /
|
|
41
|
+
* secret detection patterns,
|
|
42
|
+
* - OpenTelemetry GenAI semantic-conventions conformance helpers,
|
|
43
|
+
* - OpenInference span-kind emission,
|
|
44
|
+
* - the structured `Logger` with span correlation,
|
|
45
|
+
* - the append-only `JSONLExporter` for replay,
|
|
46
|
+
* - sanitized-by-default `Replay` primitives,
|
|
47
|
+
* - the hierarchical `CostTracker`,
|
|
48
|
+
* - and a minimal inline eval runner.
|
|
49
|
+
*
|
|
50
|
+
* The full documentation lives in the package `README.md`.
|
|
51
|
+
*
|
|
52
|
+
* @packageDocumentation
|
|
53
|
+
*/
|
|
54
|
+
/** Canonical version constant. Mirrors the `package.json` version. */
|
|
55
|
+
declare const VERSION = "0.5.0";
|
|
56
|
+
//#endregion
|
|
57
|
+
export { ALL_BUILT_IN_PATTERNS, BUILT_IN_IMPERATIVE_PATTERNS, BUILT_IN_PATTERNS, BuiltInPatternName, Case, ConsoleExporterOptions, CostBudgetExceededCallback, CostBudgets, CostRecordInput, CostScope, CostSnapshot, CostTracker, CostTrackerOptions, DEFAULT_REPLAY_LOG_CONFIG, DEFAULT_VALIDATION_CONFIG, Dataset, EvalCaseResult, EvalReport, GenAIAttributes, GenAIMessage, GenAIMessageRole, GenAIOperationName, GenAISystem, GenAIToolType, GraphorinSpan, GraphorinTracer, IMPERATIVE_PREFILTER_SUBSTRINGS, ImperativePattern, ImperativePatternName, ScanResult as ImperativeScanResult, JSONLExporterOptions, LoggerFormat, LoggerOptions, OPEN_INFERENCE_EXCLUDED_TYPES, OPEN_INFERENCE_KIND_TABLE, OPERATION_NAME_TABLE, OPT_IN_PATTERNS, OTLPHttpExporterOptions, OpenInferenceSpanKind, PROVIDER_CLASS_TO_GEN_AI_SYSTEM, PatternCategory, PruneTracesOptions, RedactionCounters, RedactionInput, RedactionOutput, RedactionPattern, RedactionValidationError, RedactionValidator, RedactionValidatorInstance, RedactionValidatorOptions, RedactionViolation, RedactionViolationCallback, Replay, ReplayAuditBridge, ReplayAuditEvent, ReplayEvent, ReplayLogConfig, ReplayMode, ReplayOptions, ReplayRunInput, RunEvalOptions, Sampler, SamplingDecisionMaker, SamplingOptions, SamplingRule, ScoreResult, Scorer, SetAttributeOptions, SpanRecord, SpanRecordEvent, SpanTypeToOperationName, TelemetryStatus, TraceExporter, TracerOptions, UnvalidatedExporterError, VALIDATED_EXPORTER_BRAND, VERSION, ValidationConfig, WithValidationOptions, _resetGenAISystemWarningsForTesting, announceTelemetryPosture, asGraphorinSpan, compareSensitivityTiers, createConsoleExporter, createCostTracker, createJSONLExporter, createLogger, createOTLPHttpExporter, createRedactionValidator, createReplay, createSampler, createTracer, deriveGenAISystem, emitGenAIAttributes, emitGenAIMessageEvents, emitOpenInferenceKind, enableTelemetry, getCurrentSpanContext, getTelemetryStatus, getTraceLog, isValidatedExporter, newSpanId, newTraceId, openInferenceKindFor, operationNameFor, pruneTraces, runEval, scanImperativePatterns, setGenAISystemWarnSink, spanNameFor, stripImperativePatterns, tryGetValidatorCounters, withCurrentSpan, withValidation };
|
|
58
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAsBa,OAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { createCostTracker } from "./cost/cost-tracker.js";
|
|
2
|
+
import "./cost/index.js";
|
|
3
|
+
import { runEval } from "./eval/runner.js";
|
|
4
|
+
import { createConsoleExporter } from "./exporters/console.js";
|
|
5
|
+
import { createJSONLExporter } from "./exporters/jsonl.js";
|
|
6
|
+
import { createOTLPHttpExporter } from "./exporters/otlp-http.js";
|
|
7
|
+
import { VALIDATED_EXPORTER_BRAND } from "./exporters/types.js";
|
|
8
|
+
import { RedactionValidationError, UnvalidatedExporterError } from "./redaction/errors.js";
|
|
9
|
+
import { ALL_BUILT_IN_PATTERNS, BUILT_IN_PATTERNS, OPT_IN_PATTERNS } from "./redaction/patterns.js";
|
|
10
|
+
import { compareSensitivityTiers, createRedactionValidator } from "./redaction/validator.js";
|
|
11
|
+
import { isValidatedExporter, tryGetValidatorCounters, withValidation } from "./exporters/with-validation.js";
|
|
12
|
+
import "./exporters/index.js";
|
|
13
|
+
import { newSpanId, newTraceId } from "./tracer/ids.js";
|
|
14
|
+
import { createSampler } from "./tracer/sampling.js";
|
|
15
|
+
import { spanNameFor } from "./tracer/span-names.js";
|
|
16
|
+
import { asGraphorinSpan, createTracer } from "./tracer/tracer.js";
|
|
17
|
+
import { OPERATION_NAME_TABLE, operationNameFor } from "./gen-ai/operation-mapping.js";
|
|
18
|
+
import { emitGenAIAttributes, emitGenAIMessageEvents } from "./gen-ai/emit.js";
|
|
19
|
+
import { PROVIDER_CLASS_TO_GEN_AI_SYSTEM, _resetGenAISystemWarningsForTesting, deriveGenAISystem, setGenAISystemWarnSink } from "./gen-ai/system-derivation.js";
|
|
20
|
+
import "./gen-ai/index.js";
|
|
21
|
+
import { createLogger, getCurrentSpanContext, withCurrentSpan } from "./logger/logger.js";
|
|
22
|
+
import "./logger/index.js";
|
|
23
|
+
import { OPEN_INFERENCE_EXCLUDED_TYPES, OPEN_INFERENCE_KIND_TABLE, emitOpenInferenceKind, openInferenceKindFor } from "./openinference/index.js";
|
|
24
|
+
import { DEFAULT_VALIDATION_CONFIG } from "./redaction/config.js";
|
|
25
|
+
import { BUILT_IN_IMPERATIVE_PATTERNS, IMPERATIVE_PREFILTER_SUBSTRINGS, scanImperativePatterns, stripImperativePatterns } from "./redaction/imperative-patterns.js";
|
|
26
|
+
import "./redaction/index.js";
|
|
27
|
+
import { DEFAULT_REPLAY_LOG_CONFIG } from "./replay/config.js";
|
|
28
|
+
import { getTraceLog, pruneTraces } from "./replay/log.js";
|
|
29
|
+
import { createReplay } from "./replay/replay.js";
|
|
30
|
+
import "./replay/index.js";
|
|
31
|
+
import { announceTelemetryPosture, enableTelemetry, getTelemetryStatus } from "./telemetry/index.js";
|
|
32
|
+
import "./tracer/index.js";
|
|
33
|
+
|
|
34
|
+
//#region src/index.ts
|
|
35
|
+
/**
|
|
36
|
+
* @graphorin/observability — observability primitives for the
|
|
37
|
+
* Graphorin framework. Ships:
|
|
38
|
+
*
|
|
39
|
+
* - the typed `AISpan<T>` tracer over OpenTelemetry,
|
|
40
|
+
* - the **mandatory** `withValidation()` wrapper for every exporter,
|
|
41
|
+
* - the sensitivity-aware `RedactionValidator` with 14 built-in PII /
|
|
42
|
+
* secret detection patterns,
|
|
43
|
+
* - OpenTelemetry GenAI semantic-conventions conformance helpers,
|
|
44
|
+
* - OpenInference span-kind emission,
|
|
45
|
+
* - the structured `Logger` with span correlation,
|
|
46
|
+
* - the append-only `JSONLExporter` for replay,
|
|
47
|
+
* - sanitized-by-default `Replay` primitives,
|
|
48
|
+
* - the hierarchical `CostTracker`,
|
|
49
|
+
* - and a minimal inline eval runner.
|
|
50
|
+
*
|
|
51
|
+
* The full documentation lives in the package `README.md`.
|
|
52
|
+
*
|
|
53
|
+
* @packageDocumentation
|
|
54
|
+
*/
|
|
55
|
+
/** Canonical version constant. Mirrors the `package.json` version. */
|
|
56
|
+
const VERSION = "0.5.0";
|
|
57
|
+
|
|
58
|
+
//#endregion
|
|
59
|
+
export { ALL_BUILT_IN_PATTERNS, BUILT_IN_IMPERATIVE_PATTERNS, BUILT_IN_PATTERNS, DEFAULT_REPLAY_LOG_CONFIG, DEFAULT_VALIDATION_CONFIG, IMPERATIVE_PREFILTER_SUBSTRINGS, OPEN_INFERENCE_EXCLUDED_TYPES, OPEN_INFERENCE_KIND_TABLE, OPERATION_NAME_TABLE, OPT_IN_PATTERNS, PROVIDER_CLASS_TO_GEN_AI_SYSTEM, RedactionValidationError, UnvalidatedExporterError, VALIDATED_EXPORTER_BRAND, VERSION, _resetGenAISystemWarningsForTesting, announceTelemetryPosture, asGraphorinSpan, compareSensitivityTiers, createConsoleExporter, createCostTracker, createJSONLExporter, createLogger, createOTLPHttpExporter, createRedactionValidator, createReplay, createSampler, createTracer, deriveGenAISystem, emitGenAIAttributes, emitGenAIMessageEvents, emitOpenInferenceKind, enableTelemetry, getCurrentSpanContext, getTelemetryStatus, getTraceLog, isValidatedExporter, newSpanId, newTraceId, openInferenceKindFor, operationNameFor, pruneTraces, runEval, scanImperativePatterns, setGenAISystemWarnSink, spanNameFor, stripImperativePatterns, tryGetValidatorCounters, withCurrentSpan, withValidation };
|
|
60
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * @graphorin/observability — observability primitives for the\n * Graphorin framework. Ships:\n *\n * - the typed `AISpan<T>` tracer over OpenTelemetry,\n * - the **mandatory** `withValidation()` wrapper for every exporter,\n * - the sensitivity-aware `RedactionValidator` with 14 built-in PII /\n * secret detection patterns,\n * - OpenTelemetry GenAI semantic-conventions conformance helpers,\n * - OpenInference span-kind emission,\n * - the structured `Logger` with span correlation,\n * - the append-only `JSONLExporter` for replay,\n * - sanitized-by-default `Replay` primitives,\n * - the hierarchical `CostTracker`,\n * - and a minimal inline eval runner.\n *\n * The full documentation lives in the package `README.md`.\n *\n * @packageDocumentation\n */\n\n/** Canonical version constant. Mirrors the `package.json` version. */\nexport const VERSION = '0.5.0';\n\nexport * from './cost/index.js';\nexport * from './eval/index.js';\nexport * from './exporters/index.js';\nexport * from './gen-ai/index.js';\nexport * from './logger/index.js';\nexport * from './openinference/index.js';\nexport * from './redaction/index.js';\nexport * from './replay/index.js';\nexport * from './telemetry/index.js';\nexport * from './tracer/index.js';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsBA,MAAa,UAAU"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { RedactionValidatorInstance } from "../redaction/types.js";
|
|
2
|
+
import { AISpan, LogLevel, Logger, Sensitivity } from "@graphorin/core";
|
|
3
|
+
|
|
4
|
+
//#region src/logger/logger.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @stable
|
|
8
|
+
*/
|
|
9
|
+
type LoggerFormat = 'json' | 'pretty';
|
|
10
|
+
/**
|
|
11
|
+
* Configuration shape for {@link createLogger}.
|
|
12
|
+
*
|
|
13
|
+
* @stable
|
|
14
|
+
*/
|
|
15
|
+
interface LoggerOptions {
|
|
16
|
+
readonly level?: LogLevel;
|
|
17
|
+
readonly format?: LoggerFormat;
|
|
18
|
+
/** Optional validator. Logger fields flow through `validate(...)`. */
|
|
19
|
+
readonly redaction?: RedactionValidatorInstance;
|
|
20
|
+
/** Default sensitivity tier for fields. Defaults to `'internal'`. */
|
|
21
|
+
readonly defaultTier?: Sensitivity;
|
|
22
|
+
/**
|
|
23
|
+
* Sink that receives the rendered line. Defaults to writing to the
|
|
24
|
+
* appropriate `console.*` method.
|
|
25
|
+
*/
|
|
26
|
+
readonly sink?: (level: LogLevel, line: string) => void;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Run `fn` with the supplied span as the "current" log-correlation
|
|
30
|
+
* span. The logger picks up the trace + span ids automatically.
|
|
31
|
+
*
|
|
32
|
+
* @stable
|
|
33
|
+
*/
|
|
34
|
+
declare function withCurrentSpan<R>(span: AISpan | undefined, fn: () => R | Promise<R>): R | Promise<R>;
|
|
35
|
+
/**
|
|
36
|
+
* Read the current span context (if any). Useful for callers that
|
|
37
|
+
* want to attach span metadata to bespoke records.
|
|
38
|
+
*
|
|
39
|
+
* @stable
|
|
40
|
+
*/
|
|
41
|
+
declare function getCurrentSpanContext(): {
|
|
42
|
+
readonly traceId: string;
|
|
43
|
+
readonly spanId: string;
|
|
44
|
+
} | undefined;
|
|
45
|
+
/**
|
|
46
|
+
* Build a {@link Logger} configured against the supplied options.
|
|
47
|
+
*
|
|
48
|
+
* @stable
|
|
49
|
+
*/
|
|
50
|
+
declare function createLogger(opts?: LoggerOptions): Logger;
|
|
51
|
+
//#endregion
|
|
52
|
+
export { LoggerFormat, LoggerOptions, createLogger, getCurrentSpanContext, withCurrentSpan };
|
|
53
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","names":[],"sources":["../../src/logger/logger.ts"],"sourcesContent":[],"mappings":";;;;;;;;AAiEc,KAxCF,YAAA,GAwCE,MAAA,GAAA,QAAA;AAWd;AAWA;;;;UAvDiB,aAAA;mBACE;oBACC;;uBAEG;;yBAEE;;;;;0BAKC;;;;;;;;iBAmBV,yBACR,8BACI,IAAI,QAAQ,KACrB,IAAI,QAAQ;;;;;;;iBAWC,qBAAA,CAAA;;;;;;;;;iBAWA,YAAA,QAAmB,gBAAqB"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { createAsyncContext } from "@graphorin/core";
|
|
2
|
+
|
|
3
|
+
//#region src/logger/logger.ts
|
|
4
|
+
const LEVELS = [
|
|
5
|
+
"trace",
|
|
6
|
+
"debug",
|
|
7
|
+
"info",
|
|
8
|
+
"warn",
|
|
9
|
+
"error"
|
|
10
|
+
];
|
|
11
|
+
/**
|
|
12
|
+
* @internal — context used to thread the current span id through nested
|
|
13
|
+
* async calls. Exposed via {@link withCurrentSpan} below.
|
|
14
|
+
*/
|
|
15
|
+
const SPAN_CONTEXT = createAsyncContext("graphorin.observability.current-span");
|
|
16
|
+
/**
|
|
17
|
+
* Run `fn` with the supplied span as the "current" log-correlation
|
|
18
|
+
* span. The logger picks up the trace + span ids automatically.
|
|
19
|
+
*
|
|
20
|
+
* @stable
|
|
21
|
+
*/
|
|
22
|
+
function withCurrentSpan(span, fn) {
|
|
23
|
+
if (span === void 0) return fn();
|
|
24
|
+
return SPAN_CONTEXT.runAsync({
|
|
25
|
+
traceId: span.traceId,
|
|
26
|
+
spanId: span.id
|
|
27
|
+
}, async () => fn());
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Read the current span context (if any). Useful for callers that
|
|
31
|
+
* want to attach span metadata to bespoke records.
|
|
32
|
+
*
|
|
33
|
+
* @stable
|
|
34
|
+
*/
|
|
35
|
+
function getCurrentSpanContext() {
|
|
36
|
+
return SPAN_CONTEXT.get();
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Build a {@link Logger} configured against the supplied options.
|
|
40
|
+
*
|
|
41
|
+
* @stable
|
|
42
|
+
*/
|
|
43
|
+
function createLogger(opts = {}) {
|
|
44
|
+
const minLevel = LEVELS.indexOf(opts.level ?? "info");
|
|
45
|
+
const format = opts.format ?? "json";
|
|
46
|
+
const redaction = opts.redaction;
|
|
47
|
+
const defaultTier = opts.defaultTier ?? "internal";
|
|
48
|
+
const sink = opts.sink ?? defaultSink;
|
|
49
|
+
function emit(level, message, fields) {
|
|
50
|
+
if (LEVELS.indexOf(level) < minLevel) return;
|
|
51
|
+
const span = SPAN_CONTEXT.get();
|
|
52
|
+
const safeFields = sanitizeFields(fields, redaction, defaultTier);
|
|
53
|
+
const payload = {
|
|
54
|
+
level,
|
|
55
|
+
time: (/* @__PURE__ */ new Date()).toISOString(),
|
|
56
|
+
message,
|
|
57
|
+
...safeFields
|
|
58
|
+
};
|
|
59
|
+
if (span !== void 0) {
|
|
60
|
+
payload.traceId = span.traceId;
|
|
61
|
+
payload.spanId = span.spanId;
|
|
62
|
+
}
|
|
63
|
+
sink(level, format === "json" ? JSON.stringify(payload) : prettyRender(payload));
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
trace: (message, fields) => emit("trace", message, fields),
|
|
67
|
+
debug: (message, fields) => emit("debug", message, fields),
|
|
68
|
+
info: (message, fields) => emit("info", message, fields),
|
|
69
|
+
warn: (message, fields) => emit("warn", message, fields),
|
|
70
|
+
error: (message, fields) => emit("error", message, fields),
|
|
71
|
+
child(_bindings) {
|
|
72
|
+
const inherited = sanitizeFields(_bindings, redaction, defaultTier);
|
|
73
|
+
const parent = createLogger(opts);
|
|
74
|
+
return {
|
|
75
|
+
trace: (m, f) => parent.trace(m, {
|
|
76
|
+
...inherited,
|
|
77
|
+
...f
|
|
78
|
+
}),
|
|
79
|
+
debug: (m, f) => parent.debug(m, {
|
|
80
|
+
...inherited,
|
|
81
|
+
...f
|
|
82
|
+
}),
|
|
83
|
+
info: (m, f) => parent.info(m, {
|
|
84
|
+
...inherited,
|
|
85
|
+
...f
|
|
86
|
+
}),
|
|
87
|
+
warn: (m, f) => parent.warn(m, {
|
|
88
|
+
...inherited,
|
|
89
|
+
...f
|
|
90
|
+
}),
|
|
91
|
+
error: (m, f) => parent.error(m, {
|
|
92
|
+
...inherited,
|
|
93
|
+
...f
|
|
94
|
+
}),
|
|
95
|
+
child(b) {
|
|
96
|
+
return parent.child({
|
|
97
|
+
...inherited,
|
|
98
|
+
...b
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
function sanitizeFields(fields, validator, tier) {
|
|
106
|
+
if (fields === void 0) return {};
|
|
107
|
+
if (validator === void 0) return { ...fields };
|
|
108
|
+
const out = {};
|
|
109
|
+
for (const [k, v] of Object.entries(fields)) {
|
|
110
|
+
const result = validator.validate({
|
|
111
|
+
value: v,
|
|
112
|
+
tier,
|
|
113
|
+
context: { attribute: k }
|
|
114
|
+
});
|
|
115
|
+
if (result === null) continue;
|
|
116
|
+
out[k] = result.value;
|
|
117
|
+
}
|
|
118
|
+
return out;
|
|
119
|
+
}
|
|
120
|
+
function defaultSink(level, line) {
|
|
121
|
+
switch (level) {
|
|
122
|
+
case "trace":
|
|
123
|
+
case "debug":
|
|
124
|
+
console.debug(line);
|
|
125
|
+
return;
|
|
126
|
+
case "info":
|
|
127
|
+
console.info(line);
|
|
128
|
+
return;
|
|
129
|
+
case "warn":
|
|
130
|
+
console.warn(line);
|
|
131
|
+
return;
|
|
132
|
+
case "error":
|
|
133
|
+
console.error(line);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
function prettyRender(payload) {
|
|
138
|
+
const { level, time, message, ...rest } = payload;
|
|
139
|
+
const fields = Object.keys(rest).length === 0 ? "" : ` ${JSON.stringify(rest)}`;
|
|
140
|
+
return `[${String(time)}] ${String(level).toUpperCase()} ${String(message)}${fields}`;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
//#endregion
|
|
144
|
+
export { createLogger, getCurrentSpanContext, withCurrentSpan };
|
|
145
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","names":["LEVELS: ReadonlyArray<LogLevel>","defaultTier: Sensitivity","payload: Record<string, unknown>","out: Record<string, unknown>"],"sources":["../../src/logger/logger.ts"],"sourcesContent":["/**\n * `createLogger(...)` — structured logger with optional span correlation.\n *\n * The logger is a thin wrapper around `console.{log,info,warn,error}`\n * that adds:\n *\n * - structured fields,\n * - JSON or pretty rendering,\n * - automatic correlation with the current Graphorin span (the\n * {@link CurrentSpanContext} helper carries the live trace + span ids),\n * - sensitivity-aware redaction via the supplied\n * {@link RedactionValidatorInstance}.\n *\n * @packageDocumentation\n */\n\nimport type { AISpan, LogFields, Logger, LogLevel, Sensitivity } from '@graphorin/core';\n\nimport { createAsyncContext } from '@graphorin/core';\n\nimport type { RedactionValidatorInstance } from '../redaction/types.js';\n\n/**\n * @stable\n */\nexport type LoggerFormat = 'json' | 'pretty';\n\n/**\n * Configuration shape for {@link createLogger}.\n *\n * @stable\n */\nexport interface LoggerOptions {\n readonly level?: LogLevel;\n readonly format?: LoggerFormat;\n /** Optional validator. Logger fields flow through `validate(...)`. */\n readonly redaction?: RedactionValidatorInstance;\n /** Default sensitivity tier for fields. Defaults to `'internal'`. */\n readonly defaultTier?: Sensitivity;\n /**\n * Sink that receives the rendered line. Defaults to writing to the\n * appropriate `console.*` method.\n */\n readonly sink?: (level: LogLevel, line: string) => void;\n}\n\nconst LEVELS: ReadonlyArray<LogLevel> = ['trace', 'debug', 'info', 'warn', 'error'] as const;\n\n/**\n * @internal — context used to thread the current span id through nested\n * async calls. Exposed via {@link withCurrentSpan} below.\n */\nconst SPAN_CONTEXT = createAsyncContext<{ traceId: string; spanId: string }>(\n 'graphorin.observability.current-span',\n);\n\n/**\n * Run `fn` with the supplied span as the \"current\" log-correlation\n * span. The logger picks up the trace + span ids automatically.\n *\n * @stable\n */\nexport function withCurrentSpan<R>(\n span: AISpan | undefined,\n fn: () => R | Promise<R>,\n): R | Promise<R> {\n if (span === undefined) return fn();\n return SPAN_CONTEXT.runAsync({ traceId: span.traceId, spanId: span.id }, async () => fn());\n}\n\n/**\n * Read the current span context (if any). Useful for callers that\n * want to attach span metadata to bespoke records.\n *\n * @stable\n */\nexport function getCurrentSpanContext():\n | { readonly traceId: string; readonly spanId: string }\n | undefined {\n return SPAN_CONTEXT.get();\n}\n\n/**\n * Build a {@link Logger} configured against the supplied options.\n *\n * @stable\n */\nexport function createLogger(opts: LoggerOptions = {}): Logger {\n const minLevel = LEVELS.indexOf(opts.level ?? 'info');\n const format = opts.format ?? 'json';\n const redaction = opts.redaction;\n const defaultTier: Sensitivity = opts.defaultTier ?? 'internal';\n const sink = opts.sink ?? defaultSink;\n\n function emit(level: LogLevel, message: string, fields?: LogFields): void {\n const idx = LEVELS.indexOf(level);\n if (idx < minLevel) return;\n\n const span = SPAN_CONTEXT.get();\n const safeFields = sanitizeFields(fields, redaction, defaultTier);\n\n const payload: Record<string, unknown> = {\n level,\n time: new Date().toISOString(),\n message,\n ...safeFields,\n };\n if (span !== undefined) {\n payload.traceId = span.traceId;\n payload.spanId = span.spanId;\n }\n\n const line = format === 'json' ? JSON.stringify(payload) : prettyRender(payload);\n sink(level, line);\n }\n\n return {\n trace: (message, fields) => emit('trace', message, fields),\n debug: (message, fields) => emit('debug', message, fields),\n info: (message, fields) => emit('info', message, fields),\n warn: (message, fields) => emit('warn', message, fields),\n error: (message, fields) => emit('error', message, fields),\n child(_bindings: LogFields): Logger {\n const inherited = sanitizeFields(_bindings, redaction, defaultTier);\n const parent = createLogger(opts);\n return {\n trace: (m, f) => parent.trace(m, { ...inherited, ...f }),\n debug: (m, f) => parent.debug(m, { ...inherited, ...f }),\n info: (m, f) => parent.info(m, { ...inherited, ...f }),\n warn: (m, f) => parent.warn(m, { ...inherited, ...f }),\n error: (m, f) => parent.error(m, { ...inherited, ...f }),\n child(b: LogFields): Logger {\n return parent.child({ ...inherited, ...b });\n },\n };\n },\n };\n}\n\nfunction sanitizeFields(\n fields: LogFields | undefined,\n validator: RedactionValidatorInstance | undefined,\n tier: Sensitivity,\n): LogFields {\n if (fields === undefined) return {};\n if (validator === undefined) return { ...fields };\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(fields)) {\n const result = validator.validate({ value: v, tier, context: { attribute: k } });\n if (result === null) continue;\n out[k] = result.value;\n }\n return out;\n}\n\nfunction defaultSink(level: LogLevel, line: string): void {\n switch (level) {\n case 'trace':\n case 'debug':\n console.debug(line);\n return;\n case 'info':\n console.info(line);\n return;\n case 'warn':\n console.warn(line);\n return;\n case 'error':\n console.error(line);\n return;\n }\n}\n\nfunction prettyRender(payload: Record<string, unknown>): string {\n const { level, time, message, ...rest } = payload;\n const fields = Object.keys(rest).length === 0 ? '' : ` ${JSON.stringify(rest)}`;\n return `[${String(time)}] ${String(level).toUpperCase()} ${String(message)}${fields}`;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { AISpan, SpanType } from "@graphorin/core";
|
|
2
|
+
|
|
3
|
+
//#region src/openinference/index.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Canonical OpenInference span-kind enum.
|
|
7
|
+
*
|
|
8
|
+
* @stable
|
|
9
|
+
*/
|
|
10
|
+
type OpenInferenceSpanKind = 'AGENT' | 'EVALUATOR' | 'LLM' | 'TOOL' | 'RETRIEVER' | 'EMBEDDING' | 'CHAIN' | 'RERANKER';
|
|
11
|
+
/**
|
|
12
|
+
* Span types intentionally excluded from OpenInference span-kind
|
|
13
|
+
* emission per the canonical table — `skill.*`, `mcp.connect`,
|
|
14
|
+
* `mcp.list-tools`, and `replay.*` markers do not have a clean
|
|
15
|
+
* OpenInference equivalent.
|
|
16
|
+
*
|
|
17
|
+
* @stable
|
|
18
|
+
*/
|
|
19
|
+
declare const OPEN_INFERENCE_EXCLUDED_TYPES: ReadonlyArray<SpanType>;
|
|
20
|
+
/**
|
|
21
|
+
* Resolve the OpenInference span kind for a Graphorin span type.
|
|
22
|
+
* Returns `null` for types intentionally excluded from emission.
|
|
23
|
+
*
|
|
24
|
+
* @stable
|
|
25
|
+
*/
|
|
26
|
+
declare function openInferenceKindFor<T extends SpanType>(type: T): OpenInferenceSpanKind | null;
|
|
27
|
+
/**
|
|
28
|
+
* Attach the `openinference.span.kind` attribute to a span. No-op for
|
|
29
|
+
* span types that lack a clean OpenInference equivalent. The attribute
|
|
30
|
+
* is tagged `'public'` because the enum value is bounded and contains
|
|
31
|
+
* no PII.
|
|
32
|
+
*
|
|
33
|
+
* @stable
|
|
34
|
+
*/
|
|
35
|
+
declare function emitOpenInferenceKind<T extends SpanType>(span: AISpan<T>): void;
|
|
36
|
+
/**
|
|
37
|
+
* Full canonical span-to-kind table — exposed for tooling and tests
|
|
38
|
+
* that need to introspect the mapping.
|
|
39
|
+
*
|
|
40
|
+
* @stable
|
|
41
|
+
*/
|
|
42
|
+
declare const OPEN_INFERENCE_KIND_TABLE: readonly (readonly [SpanType, OpenInferenceSpanKind])[];
|
|
43
|
+
//#endregion
|
|
44
|
+
export { OPEN_INFERENCE_EXCLUDED_TYPES, OPEN_INFERENCE_KIND_TABLE, OpenInferenceSpanKind, emitOpenInferenceKind, openInferenceKindFor };
|
|
45
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/openinference/index.ts"],"sourcesContent":[],"mappings":";;;;AAoIA;;;;;KA5GY,qBAAA;;;;;;;;;cAgEC,+BAA+B,cAAc;;;;;;;iBAe1C,+BAA+B,gBAAgB,IAAI;;;;;;;;;iBAYnD,gCAAgC,gBAAgB,OAAO;;;;;;;cAiB1D,+CAAyB,UAAA"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { asGraphorinSpan } from "../tracer/tracer.js";
|
|
2
|
+
|
|
3
|
+
//#region src/openinference/index.ts
|
|
4
|
+
const KIND_TABLE = Object.freeze([
|
|
5
|
+
["agent.run", "AGENT"],
|
|
6
|
+
["agent.step", "AGENT"],
|
|
7
|
+
["agent.handoff", "AGENT"],
|
|
8
|
+
["agent.suspend", "AGENT"],
|
|
9
|
+
["agent.resume", "AGENT"],
|
|
10
|
+
["provider.generate", "LLM"],
|
|
11
|
+
["provider.stream", "LLM"],
|
|
12
|
+
["tool.execute", "TOOL"],
|
|
13
|
+
["tool.approval", "TOOL"],
|
|
14
|
+
["memory.read.working", "RETRIEVER"],
|
|
15
|
+
["memory.read.session", "RETRIEVER"],
|
|
16
|
+
["memory.read.episodic", "RETRIEVER"],
|
|
17
|
+
["memory.read.semantic", "RETRIEVER"],
|
|
18
|
+
["memory.read.procedural", "RETRIEVER"],
|
|
19
|
+
["memory.read.shared", "RETRIEVER"],
|
|
20
|
+
["memory.write.working", "RETRIEVER"],
|
|
21
|
+
["memory.write.session", "RETRIEVER"],
|
|
22
|
+
["memory.write.episodic", "RETRIEVER"],
|
|
23
|
+
["memory.write.semantic", "RETRIEVER"],
|
|
24
|
+
["memory.write.procedural", "RETRIEVER"],
|
|
25
|
+
["memory.write.shared", "RETRIEVER"],
|
|
26
|
+
["memory.search.working", "RETRIEVER"],
|
|
27
|
+
["memory.search.session", "RETRIEVER"],
|
|
28
|
+
["memory.search.episodic", "RETRIEVER"],
|
|
29
|
+
["memory.search.semantic", "RETRIEVER"],
|
|
30
|
+
["memory.search.procedural", "RETRIEVER"],
|
|
31
|
+
["memory.search.shared", "RETRIEVER"],
|
|
32
|
+
["memory.embed", "EMBEDDING"],
|
|
33
|
+
["memory.consolidate.light", "CHAIN"],
|
|
34
|
+
["memory.consolidate.standard", "CHAIN"],
|
|
35
|
+
["memory.consolidate.deep", "CHAIN"],
|
|
36
|
+
["memory.conflict", "CHAIN"],
|
|
37
|
+
["workflow.run", "CHAIN"],
|
|
38
|
+
["workflow.step", "CHAIN"],
|
|
39
|
+
["workflow.task", "CHAIN"],
|
|
40
|
+
["workflow.checkpoint", "CHAIN"],
|
|
41
|
+
["mcp.call", "TOOL"]
|
|
42
|
+
]);
|
|
43
|
+
/**
|
|
44
|
+
* Span types intentionally excluded from OpenInference span-kind
|
|
45
|
+
* emission per the canonical table — `skill.*`, `mcp.connect`,
|
|
46
|
+
* `mcp.list-tools`, and `replay.*` markers do not have a clean
|
|
47
|
+
* OpenInference equivalent.
|
|
48
|
+
*
|
|
49
|
+
* @stable
|
|
50
|
+
*/
|
|
51
|
+
const OPEN_INFERENCE_EXCLUDED_TYPES = Object.freeze([
|
|
52
|
+
"skill.activate",
|
|
53
|
+
"skill.load",
|
|
54
|
+
"mcp.connect",
|
|
55
|
+
"mcp.list-tools"
|
|
56
|
+
]);
|
|
57
|
+
const KIND_LOOKUP = new Map(KIND_TABLE);
|
|
58
|
+
/**
|
|
59
|
+
* Resolve the OpenInference span kind for a Graphorin span type.
|
|
60
|
+
* Returns `null` for types intentionally excluded from emission.
|
|
61
|
+
*
|
|
62
|
+
* @stable
|
|
63
|
+
*/
|
|
64
|
+
function openInferenceKindFor(type) {
|
|
65
|
+
return KIND_LOOKUP.get(type) ?? null;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Attach the `openinference.span.kind` attribute to a span. No-op for
|
|
69
|
+
* span types that lack a clean OpenInference equivalent. The attribute
|
|
70
|
+
* is tagged `'public'` because the enum value is bounded and contains
|
|
71
|
+
* no PII.
|
|
72
|
+
*
|
|
73
|
+
* @stable
|
|
74
|
+
*/
|
|
75
|
+
function emitOpenInferenceKind(span) {
|
|
76
|
+
const kind = KIND_LOOKUP.get(span.type);
|
|
77
|
+
if (kind === void 0) return;
|
|
78
|
+
const gs = asGraphorinSpan(span);
|
|
79
|
+
if (gs !== null) gs.setAttribute("openinference.span.kind", kind, { sensitivity: "public" });
|
|
80
|
+
else span.setAttributes({ "openinference.span.kind": kind });
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Full canonical span-to-kind table — exposed for tooling and tests
|
|
84
|
+
* that need to introspect the mapping.
|
|
85
|
+
*
|
|
86
|
+
* @stable
|
|
87
|
+
*/
|
|
88
|
+
const OPEN_INFERENCE_KIND_TABLE = KIND_TABLE;
|
|
89
|
+
|
|
90
|
+
//#endregion
|
|
91
|
+
export { OPEN_INFERENCE_EXCLUDED_TYPES, OPEN_INFERENCE_KIND_TABLE, emitOpenInferenceKind, openInferenceKindFor };
|
|
92
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["KIND_TABLE: ReadonlyArray<readonly [SpanType, OpenInferenceSpanKind]>","OPEN_INFERENCE_EXCLUDED_TYPES: ReadonlyArray<SpanType>"],"sources":["../../src/openinference/index.ts"],"sourcesContent":["/**\n * OpenInference span-kind emission. Adds the\n * `openinference.span.kind` attribute (one of `AGENT`, `EVALUATOR`,\n * `LLM`, `TOOL`, `RETRIEVER`, `EMBEDDING`, `CHAIN`) to applicable\n * Graphorin spans.\n *\n * The mapping is the canonical table published in the architecture\n * documentation. Span types without a clean OpenInference equivalent\n * (`skill.*`, `mcp.connect`, `mcp.list-tools`, `replay.*`) are NOT\n * emitted — the caller can introspect via {@link openInferenceKindFor}\n * and decide whether to log a fallback attribute.\n *\n * @packageDocumentation\n */\n\nimport type { AISpan, SpanType } from '@graphorin/core';\n\nimport { asGraphorinSpan } from '../tracer/tracer.js';\n\n/**\n * Canonical OpenInference span-kind enum.\n *\n * @stable\n */\nexport type OpenInferenceSpanKind =\n | 'AGENT'\n | 'EVALUATOR'\n | 'LLM'\n | 'TOOL'\n | 'RETRIEVER'\n | 'EMBEDDING'\n | 'CHAIN'\n | 'RERANKER';\n\nconst KIND_TABLE: ReadonlyArray<readonly [SpanType, OpenInferenceSpanKind]> = Object.freeze([\n ['agent.run', 'AGENT'],\n ['agent.step', 'AGENT'],\n ['agent.handoff', 'AGENT'],\n ['agent.suspend', 'AGENT'],\n ['agent.resume', 'AGENT'],\n\n ['provider.generate', 'LLM'],\n ['provider.stream', 'LLM'],\n\n ['tool.execute', 'TOOL'],\n ['tool.approval', 'TOOL'],\n\n ['memory.read.working', 'RETRIEVER'],\n ['memory.read.session', 'RETRIEVER'],\n ['memory.read.episodic', 'RETRIEVER'],\n ['memory.read.semantic', 'RETRIEVER'],\n ['memory.read.procedural', 'RETRIEVER'],\n ['memory.read.shared', 'RETRIEVER'],\n ['memory.write.working', 'RETRIEVER'],\n ['memory.write.session', 'RETRIEVER'],\n ['memory.write.episodic', 'RETRIEVER'],\n ['memory.write.semantic', 'RETRIEVER'],\n ['memory.write.procedural', 'RETRIEVER'],\n ['memory.write.shared', 'RETRIEVER'],\n ['memory.search.working', 'RETRIEVER'],\n ['memory.search.session', 'RETRIEVER'],\n ['memory.search.episodic', 'RETRIEVER'],\n ['memory.search.semantic', 'RETRIEVER'],\n ['memory.search.procedural', 'RETRIEVER'],\n ['memory.search.shared', 'RETRIEVER'],\n\n ['memory.embed', 'EMBEDDING'],\n\n ['memory.consolidate.light', 'CHAIN'],\n ['memory.consolidate.standard', 'CHAIN'],\n ['memory.consolidate.deep', 'CHAIN'],\n ['memory.conflict', 'CHAIN'],\n ['workflow.run', 'CHAIN'],\n ['workflow.step', 'CHAIN'],\n ['workflow.task', 'CHAIN'],\n ['workflow.checkpoint', 'CHAIN'],\n\n ['mcp.call', 'TOOL'],\n] as const);\n\n/**\n * Span types intentionally excluded from OpenInference span-kind\n * emission per the canonical table — `skill.*`, `mcp.connect`,\n * `mcp.list-tools`, and `replay.*` markers do not have a clean\n * OpenInference equivalent.\n *\n * @stable\n */\nexport const OPEN_INFERENCE_EXCLUDED_TYPES: ReadonlyArray<SpanType> = Object.freeze([\n 'skill.activate',\n 'skill.load',\n 'mcp.connect',\n 'mcp.list-tools',\n] as const);\n\nconst KIND_LOOKUP = new Map<SpanType, OpenInferenceSpanKind>(KIND_TABLE);\n\n/**\n * Resolve the OpenInference span kind for a Graphorin span type.\n * Returns `null` for types intentionally excluded from emission.\n *\n * @stable\n */\nexport function openInferenceKindFor<T extends SpanType>(type: T): OpenInferenceSpanKind | null {\n return KIND_LOOKUP.get(type) ?? null;\n}\n\n/**\n * Attach the `openinference.span.kind` attribute to a span. No-op for\n * span types that lack a clean OpenInference equivalent. The attribute\n * is tagged `'public'` because the enum value is bounded and contains\n * no PII.\n *\n * @stable\n */\nexport function emitOpenInferenceKind<T extends SpanType>(span: AISpan<T>): void {\n const kind = KIND_LOOKUP.get(span.type);\n if (kind === undefined) return;\n const gs = asGraphorinSpan(span);\n if (gs !== null) {\n gs.setAttribute('openinference.span.kind', kind, { sensitivity: 'public' });\n } else {\n span.setAttributes({ 'openinference.span.kind': kind });\n }\n}\n\n/**\n * Full canonical span-to-kind table — exposed for tooling and tests\n * that need to introspect the mapping.\n *\n * @stable\n */\nexport const OPEN_INFERENCE_KIND_TABLE = KIND_TABLE;\n"],"mappings":";;;AAkCA,MAAMA,aAAwE,OAAO,OAAO;CAC1F,CAAC,aAAa,QAAQ;CACtB,CAAC,cAAc,QAAQ;CACvB,CAAC,iBAAiB,QAAQ;CAC1B,CAAC,iBAAiB,QAAQ;CAC1B,CAAC,gBAAgB,QAAQ;CAEzB,CAAC,qBAAqB,MAAM;CAC5B,CAAC,mBAAmB,MAAM;CAE1B,CAAC,gBAAgB,OAAO;CACxB,CAAC,iBAAiB,OAAO;CAEzB,CAAC,uBAAuB,YAAY;CACpC,CAAC,uBAAuB,YAAY;CACpC,CAAC,wBAAwB,YAAY;CACrC,CAAC,wBAAwB,YAAY;CACrC,CAAC,0BAA0B,YAAY;CACvC,CAAC,sBAAsB,YAAY;CACnC,CAAC,wBAAwB,YAAY;CACrC,CAAC,wBAAwB,YAAY;CACrC,CAAC,yBAAyB,YAAY;CACtC,CAAC,yBAAyB,YAAY;CACtC,CAAC,2BAA2B,YAAY;CACxC,CAAC,uBAAuB,YAAY;CACpC,CAAC,yBAAyB,YAAY;CACtC,CAAC,yBAAyB,YAAY;CACtC,CAAC,0BAA0B,YAAY;CACvC,CAAC,0BAA0B,YAAY;CACvC,CAAC,4BAA4B,YAAY;CACzC,CAAC,wBAAwB,YAAY;CAErC,CAAC,gBAAgB,YAAY;CAE7B,CAAC,4BAA4B,QAAQ;CACrC,CAAC,+BAA+B,QAAQ;CACxC,CAAC,2BAA2B,QAAQ;CACpC,CAAC,mBAAmB,QAAQ;CAC5B,CAAC,gBAAgB,QAAQ;CACzB,CAAC,iBAAiB,QAAQ;CAC1B,CAAC,iBAAiB,QAAQ;CAC1B,CAAC,uBAAuB,QAAQ;CAEhC,CAAC,YAAY,OAAO;CACrB,CAAU;;;;;;;;;AAUX,MAAaC,gCAAyD,OAAO,OAAO;CAClF;CACA;CACA;CACA;CACD,CAAU;AAEX,MAAM,cAAc,IAAI,IAAqC,WAAW;;;;;;;AAQxE,SAAgB,qBAAyC,MAAuC;AAC9F,QAAO,YAAY,IAAI,KAAK,IAAI;;;;;;;;;;AAWlC,SAAgB,sBAA0C,MAAuB;CAC/E,MAAM,OAAO,YAAY,IAAI,KAAK,KAAK;AACvC,KAAI,SAAS,OAAW;CACxB,MAAM,KAAK,gBAAgB,KAAK;AAChC,KAAI,OAAO,KACT,IAAG,aAAa,2BAA2B,MAAM,EAAE,aAAa,UAAU,CAAC;KAE3E,MAAK,cAAc,EAAE,2BAA2B,MAAM,CAAC;;;;;;;;AAU3D,MAAa,4BAA4B"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { RedactionPattern } from "./patterns.js";
|
|
2
|
+
import { Sensitivity } from "@graphorin/core";
|
|
3
|
+
|
|
4
|
+
//#region src/redaction/config.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @stable
|
|
8
|
+
*/
|
|
9
|
+
interface ValidationConfig {
|
|
10
|
+
/** Lowest tier that may pass through the validator. */
|
|
11
|
+
readonly minTier?: Sensitivity;
|
|
12
|
+
/**
|
|
13
|
+
* When `true`, the validator throws on dropped values instead of
|
|
14
|
+
* silently dropping + counting. Use in tests; production should
|
|
15
|
+
* keep the default.
|
|
16
|
+
*
|
|
17
|
+
* @default false
|
|
18
|
+
*/
|
|
19
|
+
readonly failOnUnredactedSensitive?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Custom pattern catalogue. Defaults to the 14 default-on built-in
|
|
22
|
+
* patterns.
|
|
23
|
+
*/
|
|
24
|
+
readonly patterns?: ReadonlyArray<RedactionPattern>;
|
|
25
|
+
/** Per-name allow-list. */
|
|
26
|
+
readonly enabledPatterns?: ReadonlyArray<string>;
|
|
27
|
+
/** Per-name deny-list. */
|
|
28
|
+
readonly disabledPatterns?: ReadonlyArray<string>;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Default validation configuration. Mirrors the runtime defaults used
|
|
32
|
+
* by `createTracer({ ... })` when `validation` is omitted.
|
|
33
|
+
*
|
|
34
|
+
* @stable
|
|
35
|
+
*/
|
|
36
|
+
declare const DEFAULT_VALIDATION_CONFIG: Required<Pick<ValidationConfig, 'minTier' | 'failOnUnredactedSensitive'>>;
|
|
37
|
+
//#endregion
|
|
38
|
+
export { DEFAULT_VALIDATION_CONFIG, ValidationConfig };
|
|
39
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","names":[],"sources":["../../src/redaction/config.ts"],"sourcesContent":[],"mappings":";;;;;;AA4CA;;AACE,UA7Be,gBAAA,CA6Bf;EADsC;EAAQ,SAAA,OAAA,CAAA,EA1B3B,WA0B2B;;;;;;;;;;;;;sBAb1B,cAAc;;6BAEP;;8BAEC;;;;;;;;cASjB,2BAA2B,SACtC,KAAK"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//#region src/redaction/config.ts
|
|
2
|
+
/**
|
|
3
|
+
* Default validation configuration. Mirrors the runtime defaults used
|
|
4
|
+
* by `createTracer({ ... })` when `validation` is omitted.
|
|
5
|
+
*
|
|
6
|
+
* @stable
|
|
7
|
+
*/
|
|
8
|
+
const DEFAULT_VALIDATION_CONFIG = Object.freeze({
|
|
9
|
+
minTier: "public",
|
|
10
|
+
failOnUnredactedSensitive: false
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
//#endregion
|
|
14
|
+
export { DEFAULT_VALIDATION_CONFIG };
|
|
15
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","names":["DEFAULT_VALIDATION_CONFIG: Required<\n Pick<ValidationConfig, 'minTier' | 'failOnUnredactedSensitive'>\n>"],"sources":["../../src/redaction/config.ts"],"sourcesContent":["/**\n * Configuration shape consumed by `observability.validation.*`.\n *\n * The shape mirrors the canonical settings so consumer configuration\n * files can use a single typed structure.\n *\n * @packageDocumentation\n */\n\nimport type { Sensitivity } from '@graphorin/core';\n\nimport type { RedactionPattern } from './patterns.js';\n\n/**\n * @stable\n */\nexport interface ValidationConfig {\n /** Lowest tier that may pass through the validator. */\n readonly minTier?: Sensitivity;\n /**\n * When `true`, the validator throws on dropped values instead of\n * silently dropping + counting. Use in tests; production should\n * keep the default.\n *\n * @default false\n */\n readonly failOnUnredactedSensitive?: boolean;\n /**\n * Custom pattern catalogue. Defaults to the 14 default-on built-in\n * patterns.\n */\n readonly patterns?: ReadonlyArray<RedactionPattern>;\n /** Per-name allow-list. */\n readonly enabledPatterns?: ReadonlyArray<string>;\n /** Per-name deny-list. */\n readonly disabledPatterns?: ReadonlyArray<string>;\n}\n\n/**\n * Default validation configuration. Mirrors the runtime defaults used\n * by `createTracer({ ... })` when `validation` is omitted.\n *\n * @stable\n */\nexport const DEFAULT_VALIDATION_CONFIG: Required<\n Pick<ValidationConfig, 'minTier' | 'failOnUnredactedSensitive'>\n> = Object.freeze({\n minTier: 'public' as const,\n failOnUnredactedSensitive: false,\n});\n"],"mappings":";;;;;;;AA4CA,MAAaA,4BAET,OAAO,OAAO;CAChB,SAAS;CACT,2BAA2B;CAC5B,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { RedactionViolation } from "./types.js";
|
|
2
|
+
|
|
3
|
+
//#region src/redaction/errors.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Thrown by the validator when `failOnUnredactedSensitive: true` and
|
|
7
|
+
* a value would otherwise be dropped or masked. The error never
|
|
8
|
+
* carries the secret value itself; only the sanitized
|
|
9
|
+
* {@link RedactionViolation} metadata.
|
|
10
|
+
*
|
|
11
|
+
* @stable
|
|
12
|
+
*/
|
|
13
|
+
declare class RedactionValidationError extends Error {
|
|
14
|
+
/** @stable */
|
|
15
|
+
readonly kind: "redaction-validation-failed";
|
|
16
|
+
/** @stable */
|
|
17
|
+
readonly violation: RedactionViolation;
|
|
18
|
+
constructor(message: string, violation: RedactionViolation);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Thrown at startup when an exporter is registered without going
|
|
22
|
+
* through `withValidation(...)`. Enforces ADR-035: every exporter
|
|
23
|
+
* must validate before forwarding.
|
|
24
|
+
*
|
|
25
|
+
* @stable
|
|
26
|
+
*/
|
|
27
|
+
declare class UnvalidatedExporterError extends Error {
|
|
28
|
+
/** @stable */
|
|
29
|
+
readonly kind: "unvalidated-exporter";
|
|
30
|
+
/** Exporter identifier (typically `exporter.constructor.name`). */
|
|
31
|
+
readonly exporterId: string;
|
|
32
|
+
constructor(exporterId: string);
|
|
33
|
+
}
|
|
34
|
+
//#endregion
|
|
35
|
+
export { RedactionValidationError, UnvalidatedExporterError };
|
|
36
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","names":[],"sources":["../../src/redaction/errors.ts"],"sourcesContent":[],"mappings":";;;;;;AAoCA;;;;;;cApBa,wBAAA,SAAiC,KAAA;;;;sBAIxB;0CAEoB;;;;;;;;;cAc7B,wBAAA,SAAiC,KAAA"}
|