agentic-pi 0.2.3 → 0.2.5

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.
@@ -0,0 +1,334 @@
1
+ /**
2
+ * Translates Pi's raw session event stream into an OpenTelemetry span tree
3
+ * plus metrics.
4
+ *
5
+ * Span tree (one-shot run → short-lived, so a real root span is correct):
6
+ *
7
+ * agentic_pi.session (root)
8
+ * └── agentic_pi.turn (per turn_start/turn_end)
9
+ * ├── chat <model> (per assistant message_start→message_end)
10
+ * └── execute_tool <name> (per tool_execution_start→end, keyed by toolCallId)
11
+ *
12
+ * Spans and metrics are both sourced from the SAME per-message / per-tool
13
+ * events (never from the aggregate session stats), so they agree and nothing
14
+ * is double-counted. Aggregate stats only decorate the root span.
15
+ *
16
+ * Every public method is defensive: missing/out-of-order pairs warn once and
17
+ * never throw — a telemetry glitch must never break the run.
18
+ */
19
+ import { SpanKind, SpanStatusCode, ValueType, trace, } from "@opentelemetry/api";
20
+ import { AgenticPi, GenAI, MetricName, SpanName, TokenType } from "./semconv.js";
21
+ import { redact } from "./config.js";
22
+ export class SpanMapper {
23
+ d;
24
+ now;
25
+ inst;
26
+ rootSpan;
27
+ rootCtx;
28
+ turnSpan;
29
+ turnCtx;
30
+ turnIndex = 0;
31
+ llm;
32
+ toolSpans = new Map();
33
+ ended = false;
34
+ warnedUnknownTool = false;
35
+ constructor(deps) {
36
+ this.d = deps;
37
+ this.now = deps.now ?? (() => Date.now());
38
+ this.inst = this.buildInstruments(deps.meter);
39
+ }
40
+ onEvent(event) {
41
+ if (this.ended)
42
+ return;
43
+ try {
44
+ this.ensureRoot();
45
+ switch (event.type) {
46
+ case "turn_start":
47
+ this.onTurnStart();
48
+ break;
49
+ case "turn_end":
50
+ this.onTurnEnd();
51
+ break;
52
+ case "message_start":
53
+ this.onMessageStart(event.message);
54
+ break;
55
+ case "message_end":
56
+ this.onMessageEnd(event.message);
57
+ break;
58
+ case "tool_execution_start":
59
+ this.onToolStart(event.toolCallId, event.toolName, event.args);
60
+ break;
61
+ case "tool_execution_end":
62
+ this.onToolEnd(event.toolCallId, event.toolName, event.result, event.isError);
63
+ break;
64
+ case "agent_end":
65
+ this.onAgentEnd();
66
+ break;
67
+ default:
68
+ break;
69
+ }
70
+ }
71
+ catch (err) {
72
+ this.d.onWarn(`telemetry: failed to map ${event.type}: ${err.message}`);
73
+ }
74
+ }
75
+ /** Decorate the root span with terminal aggregate stats (reconciliation only). */
76
+ recordSessionStats(stats) {
77
+ if (this.ended)
78
+ return;
79
+ const root = this.rootSpan;
80
+ if (!root)
81
+ return;
82
+ if (typeof stats.cost === "number")
83
+ root.setAttribute(AgenticPi.COST_USD, stats.cost);
84
+ if (typeof stats.tokens?.total === "number") {
85
+ root.setAttribute(AgenticPi.TOTAL_TOKENS, stats.tokens.total);
86
+ }
87
+ }
88
+ /** Mark the root span as errored (called before shutdown on the fatal path). */
89
+ recordFatal(err) {
90
+ if (this.ended)
91
+ return;
92
+ this.ensureRoot();
93
+ this.rootSpan?.recordException(err);
94
+ this.rootSpan?.setStatus({ code: SpanStatusCode.ERROR, message: err.message });
95
+ }
96
+ /** Close any still-open spans (ERROR) and end the root. Idempotent. */
97
+ end() {
98
+ if (this.ended)
99
+ return;
100
+ this.ended = true;
101
+ const abandon = (s) => {
102
+ if (!s)
103
+ return;
104
+ s.setStatus({ code: SpanStatusCode.ERROR, message: "span not closed before shutdown" });
105
+ s.end();
106
+ };
107
+ for (const { span } of this.toolSpans.values())
108
+ abandon(span);
109
+ this.toolSpans.clear();
110
+ abandon(this.llm?.span);
111
+ this.llm = undefined;
112
+ abandon(this.turnSpan);
113
+ this.turnSpan = undefined;
114
+ this.turnCtx = undefined;
115
+ // Root may already carry an OK/ERROR status from agent_end / recordFatal;
116
+ // end() without overriding so a clean run stays clean.
117
+ this.rootSpan?.end();
118
+ this.rootSpan = undefined;
119
+ }
120
+ // ── event handlers ────────────────────────────────────────────────
121
+ ensureRoot() {
122
+ if (this.rootSpan)
123
+ return;
124
+ this.rootCtx = this.d.rootParentContext;
125
+ this.rootSpan = this.d.tracer.startSpan(SpanName.SESSION, {
126
+ kind: SpanKind.INTERNAL,
127
+ attributes: {
128
+ [GenAI.CONVERSATION_ID]: this.d.sessionId,
129
+ [GenAI.SYSTEM]: this.d.genAiSystem,
130
+ [GenAI.REQUEST_MODEL]: this.d.requestModel,
131
+ [AgenticPi.SANDBOX_BACKEND]: this.d.sandboxBackend,
132
+ },
133
+ }, this.rootCtx);
134
+ }
135
+ parentCtx() {
136
+ return this.turnCtx ?? trace.setSpan(this.rootCtx, this.rootSpan);
137
+ }
138
+ onTurnStart() {
139
+ if (this.turnSpan)
140
+ this.abandonTurn();
141
+ const idx = this.turnIndex++;
142
+ const parent = trace.setSpan(this.rootCtx, this.rootSpan);
143
+ this.turnSpan = this.d.tracer.startSpan(SpanName.TURN, { kind: SpanKind.INTERNAL, attributes: { [AgenticPi.TURN_INDEX]: idx } }, parent);
144
+ this.turnCtx = trace.setSpan(parent, this.turnSpan);
145
+ this.inst.turns.add(1);
146
+ }
147
+ onTurnEnd() {
148
+ // Close a dangling LLM span first so it nests inside the turn.
149
+ if (this.llm) {
150
+ this.llm.span.end();
151
+ this.llm = undefined;
152
+ }
153
+ this.turnSpan?.end();
154
+ this.turnSpan = undefined;
155
+ this.turnCtx = undefined;
156
+ }
157
+ onMessageStart(message) {
158
+ if (message.role !== "assistant")
159
+ return;
160
+ const model = message.model ?? this.d.requestModel;
161
+ const span = this.d.tracer.startSpan(SpanName.llm(model), {
162
+ kind: SpanKind.CLIENT,
163
+ attributes: {
164
+ [GenAI.OPERATION_NAME]: "chat",
165
+ [GenAI.SYSTEM]: message.provider ?? this.d.genAiSystem,
166
+ [GenAI.REQUEST_MODEL]: model,
167
+ },
168
+ }, this.parentCtx());
169
+ this.llm = { span, startMs: this.now() };
170
+ }
171
+ onMessageEnd(message) {
172
+ if (message.role !== "assistant")
173
+ return;
174
+ // message_start may have been missed; open a zero-duration span now.
175
+ if (!this.llm) {
176
+ const model = message.model ?? this.d.requestModel;
177
+ this.llm = {
178
+ span: this.d.tracer.startSpan(SpanName.llm(model), { kind: SpanKind.CLIENT }, this.parentCtx()),
179
+ startMs: this.now(),
180
+ };
181
+ }
182
+ const { span, startMs } = this.llm;
183
+ const system = message.provider ?? this.d.genAiSystem;
184
+ const model = message.model ?? this.d.requestModel;
185
+ const usage = message.usage;
186
+ span.setAttribute(GenAI.RESPONSE_MODEL, message.responseModel ?? model);
187
+ if (message.responseId)
188
+ span.setAttribute(GenAI.RESPONSE_ID, message.responseId);
189
+ if (message.stopReason)
190
+ span.setAttribute(GenAI.RESPONSE_FINISH_REASONS, [message.stopReason]);
191
+ if (usage) {
192
+ const dims = { [GenAI.SYSTEM]: system, [GenAI.REQUEST_MODEL]: model };
193
+ this.setAndMeasureToken(span, GenAI.USAGE_INPUT_TOKENS, usage.input, TokenType.INPUT, dims);
194
+ this.setAndMeasureToken(span, GenAI.USAGE_OUTPUT_TOKENS, usage.output, TokenType.OUTPUT, dims);
195
+ this.setAndMeasureToken(span, AgenticPi.CACHE_READ_TOKENS, usage.cacheRead, TokenType.CACHE_READ, dims);
196
+ this.setAndMeasureToken(span, AgenticPi.CACHE_WRITE_TOKENS, usage.cacheWrite, TokenType.CACHE_WRITE, dims);
197
+ const cost = usage.cost?.total;
198
+ if (typeof cost === "number") {
199
+ span.setAttribute(AgenticPi.COST_USD, cost);
200
+ this.inst.cost.record(cost, dims);
201
+ }
202
+ }
203
+ const content = redact(this.assistantText(message), this.d.includeContent);
204
+ if (content !== undefined)
205
+ span.setAttribute(GenAI.COMPLETION, content);
206
+ const durationS = (this.now() - startMs) / 1000;
207
+ this.inst.llmDuration.record(durationS, {
208
+ [GenAI.SYSTEM]: system,
209
+ [GenAI.REQUEST_MODEL]: model,
210
+ });
211
+ span.end();
212
+ this.llm = undefined;
213
+ }
214
+ onToolStart(toolCallId, toolName, args) {
215
+ const span = this.d.tracer.startSpan(SpanName.tool(toolName), {
216
+ kind: SpanKind.INTERNAL,
217
+ attributes: { [GenAI.TOOL_NAME]: toolName, [GenAI.TOOL_CALL_ID]: toolCallId },
218
+ }, this.parentCtx());
219
+ const argStr = redact(args, this.d.includeContent);
220
+ if (argStr !== undefined)
221
+ span.setAttribute(AgenticPi.TOOL_ARGUMENTS, argStr);
222
+ this.toolSpans.set(toolCallId, { span, startMs: this.now() });
223
+ this.inst.toolInvocations.add(1, { [GenAI.TOOL_NAME]: toolName });
224
+ }
225
+ onToolEnd(toolCallId, toolName, result, isError) {
226
+ let entry = this.toolSpans.get(toolCallId);
227
+ if (!entry) {
228
+ if (!this.warnedUnknownTool) {
229
+ this.warnedUnknownTool = true;
230
+ this.d.onWarn(`telemetry: tool_execution_end for unknown toolCallId ${toolCallId}`);
231
+ }
232
+ entry = {
233
+ span: this.d.tracer.startSpan(SpanName.tool(toolName), {
234
+ kind: SpanKind.INTERNAL,
235
+ attributes: { [GenAI.TOOL_NAME]: toolName, [GenAI.TOOL_CALL_ID]: toolCallId },
236
+ }, this.parentCtx()),
237
+ startMs: this.now(),
238
+ };
239
+ }
240
+ const { span, startMs } = entry;
241
+ span.setAttribute(AgenticPi.TOOL_IS_ERROR, isError);
242
+ const resultStr = redact(result, this.d.includeContent);
243
+ if (resultStr !== undefined)
244
+ span.setAttribute(AgenticPi.TOOL_RESULT, resultStr);
245
+ if (isError) {
246
+ span.setStatus({ code: SpanStatusCode.ERROR });
247
+ this.inst.toolFailures.add(1, { [GenAI.TOOL_NAME]: toolName });
248
+ }
249
+ this.inst.toolDuration.record((this.now() - startMs) / 1000, { [GenAI.TOOL_NAME]: toolName });
250
+ span.end();
251
+ this.toolSpans.delete(toolCallId);
252
+ }
253
+ onAgentEnd() {
254
+ if (this.llm) {
255
+ this.llm.span.end();
256
+ this.llm = undefined;
257
+ }
258
+ if (this.turnSpan)
259
+ this.abandonTurn();
260
+ // Mark success but DO NOT end the root span yet: getSessionStats() runs
261
+ // after prompt() returns (i.e. after this event), and recordSessionStats()
262
+ // needs the root span still open to attach aggregate totals. end() — called
263
+ // from shutdown() — closes it, preserving this OK status.
264
+ this.rootSpan?.setStatus({ code: SpanStatusCode.OK });
265
+ }
266
+ // ── helpers ───────────────────────────────────────────────────────
267
+ setAndMeasureToken(span, attrKey, value, tokenType, dims) {
268
+ if (typeof value !== "number" || value === 0)
269
+ return;
270
+ span.setAttribute(attrKey, value);
271
+ this.inst.tokens.record(value, { ...dims, [GenAI.TOKEN_TYPE]: tokenType });
272
+ }
273
+ abandonTurn() {
274
+ this.turnSpan?.setStatus({
275
+ code: SpanStatusCode.ERROR,
276
+ message: "turn not closed before next turn_start",
277
+ });
278
+ this.turnSpan?.end();
279
+ this.turnSpan = undefined;
280
+ this.turnCtx = undefined;
281
+ }
282
+ assistantText(message) {
283
+ const content = message.content;
284
+ if (typeof content === "string")
285
+ return content;
286
+ if (!Array.isArray(content))
287
+ return undefined;
288
+ const text = content
289
+ .filter((c) => typeof c === "object" && c !== null && c.type === "text")
290
+ .map((c) => c.text ?? "")
291
+ .join("");
292
+ return text.length > 0 ? text : undefined;
293
+ }
294
+ buildInstruments(meter) {
295
+ return {
296
+ tokens: meter.createHistogram(MetricName.LLM_TOKENS, {
297
+ description: "Number of tokens used per LLM request, by token type.",
298
+ unit: "{token}",
299
+ valueType: ValueType.INT,
300
+ }),
301
+ llmDuration: meter.createHistogram(MetricName.LLM_DURATION, {
302
+ description: "Duration of LLM requests.",
303
+ unit: "s",
304
+ valueType: ValueType.DOUBLE,
305
+ }),
306
+ cost: meter.createHistogram(MetricName.COST, {
307
+ description: "Estimated cost per LLM request in USD.",
308
+ unit: "{usd}",
309
+ valueType: ValueType.DOUBLE,
310
+ }),
311
+ toolDuration: meter.createHistogram(MetricName.TOOL_DURATION, {
312
+ description: "Duration of tool executions.",
313
+ unit: "s",
314
+ valueType: ValueType.DOUBLE,
315
+ }),
316
+ toolInvocations: meter.createCounter(MetricName.TOOL_INVOCATIONS, {
317
+ description: "Count of tool invocations.",
318
+ unit: "{call}",
319
+ valueType: ValueType.INT,
320
+ }),
321
+ toolFailures: meter.createCounter(MetricName.TOOL_FAILURES, {
322
+ description: "Count of tool invocations that returned an error.",
323
+ unit: "{call}",
324
+ valueType: ValueType.INT,
325
+ }),
326
+ turns: meter.createCounter(MetricName.TURNS, {
327
+ description: "Count of agent turns.",
328
+ unit: "{turn}",
329
+ valueType: ValueType.INT,
330
+ }),
331
+ };
332
+ }
333
+ }
334
+ //# sourceMappingURL=mapper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapper.js","sourceRoot":"","sources":["../../src/telemetry/mapper.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * OpenTelemetry SDK construction. Imported dynamically (only on the enabled
3
+ * path) so the heavy `@opentelemetry/sdk-*` packages stay off the default
4
+ * code path.
5
+ *
6
+ * Diagnostics from the SDK and OTLP exporters are routed to `onWarn` via a
7
+ * custom `DiagLogger` that NEVER touches the console — this, plus using the
8
+ * granular SDK packages (not `@opentelemetry/sdk-node`, whose auto-config can
9
+ * log to stdout), is what keeps the `run()` no-stdout contract intact even
10
+ * when the collector is unreachable.
11
+ */
12
+ import type { CreateTelemetryDeps, TelemetryHandle } from "./index.js";
13
+ export declare function startTelemetrySdk(deps: CreateTelemetryDeps): TelemetryHandle;
@@ -0,0 +1,147 @@
1
+ /**
2
+ * OpenTelemetry SDK construction. Imported dynamically (only on the enabled
3
+ * path) so the heavy `@opentelemetry/sdk-*` packages stay off the default
4
+ * code path.
5
+ *
6
+ * Diagnostics from the SDK and OTLP exporters are routed to `onWarn` via a
7
+ * custom `DiagLogger` that NEVER touches the console — this, plus using the
8
+ * granular SDK packages (not `@opentelemetry/sdk-node`, whose auto-config can
9
+ * log to stdout), is what keeps the `run()` no-stdout contract intact even
10
+ * when the collector is unreachable.
11
+ */
12
+ import { DiagLogLevel, ROOT_CONTEXT, defaultTextMapGetter, diag, } from "@opentelemetry/api";
13
+ import { W3CTraceContextPropagator } from "@opentelemetry/core";
14
+ import { defaultResource, detectResources, envDetector, resourceFromAttributes } from "@opentelemetry/resources";
15
+ import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";
16
+ import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
17
+ import { MeterProvider, PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics";
18
+ import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
19
+ import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http";
20
+ import { SpanMapper } from "./mapper.js";
21
+ import { DEFAULT_SERVICE_NAME, GenAI } from "./semconv.js";
22
+ const SHUTDOWN_TIMEOUT_MS = 5000;
23
+ const INSTRUMENTATION_SCOPE = "agentic-pi";
24
+ /** Route SDK/exporter diagnostics to onWarn — never to the console. */
25
+ class OnWarnDiagLogger {
26
+ onWarn;
27
+ constructor(onWarn) {
28
+ this.onWarn = onWarn;
29
+ }
30
+ error(message) {
31
+ this.onWarn(`otel: ${message}`);
32
+ }
33
+ warn(message) {
34
+ this.onWarn(`otel: ${message}`);
35
+ }
36
+ info() { }
37
+ debug() { }
38
+ verbose() { }
39
+ }
40
+ export function startTelemetrySdk(deps) {
41
+ const env = deps.env ?? process.env;
42
+ const onWarn = deps.onWarn;
43
+ diag.setLogger(new OnWarnDiagLogger(onWarn), DiagLogLevel.WARN);
44
+ const { provider, modelId } = splitModel(deps.model);
45
+ const serviceName = deps.config.serviceName ?? DEFAULT_SERVICE_NAME;
46
+ if (!hasOtlpTarget(env, deps.config.endpoint)) {
47
+ onWarn("telemetry: enabled but no OTLP endpoint configured (set OTEL_EXPORTER_OTLP_ENDPOINT or --otel-endpoint); spans/metrics will not be exported");
48
+ }
49
+ const resource = defaultResource()
50
+ .merge(detectResources({ detectors: [envDetector] }))
51
+ .merge(resourceFromAttributes({
52
+ "service.name": serviceName,
53
+ [GenAI.SYSTEM]: provider,
54
+ }));
55
+ const traceUrl = signalUrl(deps.config.endpoint, "v1/traces");
56
+ const metricUrl = signalUrl(deps.config.endpoint, "v1/metrics");
57
+ const tracerProvider = new NodeTracerProvider({
58
+ resource,
59
+ spanProcessors: env.OTEL_TRACES_EXPORTER === "none"
60
+ ? []
61
+ : [new BatchSpanProcessor(new OTLPTraceExporter(traceUrl ? { url: traceUrl } : {}))],
62
+ });
63
+ const meterProvider = new MeterProvider({
64
+ resource,
65
+ readers: env.OTEL_METRICS_EXPORTER === "none"
66
+ ? []
67
+ : [
68
+ new PeriodicExportingMetricReader({
69
+ exporter: new OTLPMetricExporter(metricUrl ? { url: metricUrl } : {}),
70
+ }),
71
+ ],
72
+ });
73
+ // We deliberately do NOT register these providers globally: agentic-pi may
74
+ // run multiple sessions in-process (library mode), and a global install
75
+ // would leak state across runs. Spans are created from this tracer with
76
+ // explicit parent contexts instead.
77
+ const tracer = tracerProvider.getTracer(INSTRUMENTATION_SCOPE);
78
+ const meter = meterProvider.getMeter(INSTRUMENTATION_SCOPE);
79
+ const rootParentContext = resolveInboundContext(env);
80
+ const mapper = new SpanMapper({
81
+ tracer,
82
+ meter,
83
+ rootParentContext,
84
+ sessionId: deps.sessionId,
85
+ genAiSystem: provider,
86
+ requestModel: modelId,
87
+ sandboxBackend: deps.sandboxBackend,
88
+ includeContent: deps.config.includeContent,
89
+ onWarn,
90
+ });
91
+ return {
92
+ status: "configured",
93
+ onEvent: (event) => mapper.onEvent(event),
94
+ recordSessionStats: (stats) => mapper.recordSessionStats(stats),
95
+ recordFatal: (err) => mapper.recordFatal(err),
96
+ shutdown: async () => {
97
+ mapper.end();
98
+ await withTimeout(Promise.allSettled([tracerProvider.shutdown(), meterProvider.shutdown()]), SHUTDOWN_TIMEOUT_MS, onWarn);
99
+ diag.disable();
100
+ },
101
+ };
102
+ }
103
+ function resolveInboundContext(env) {
104
+ const traceparent = env.TRACEPARENT;
105
+ if (!traceparent)
106
+ return ROOT_CONTEXT;
107
+ const carrier = { traceparent };
108
+ if (env.TRACESTATE)
109
+ carrier.tracestate = env.TRACESTATE;
110
+ return new W3CTraceContextPropagator().extract(ROOT_CONTEXT, carrier, defaultTextMapGetter);
111
+ }
112
+ function splitModel(spec) {
113
+ const i = spec.indexOf("/");
114
+ if (i < 0)
115
+ return { provider: "unknown", modelId: spec };
116
+ return { provider: spec.slice(0, i), modelId: spec.slice(i + 1) };
117
+ }
118
+ function hasOtlpTarget(env, endpoint) {
119
+ return Boolean(endpoint ||
120
+ env.OTEL_EXPORTER_OTLP_ENDPOINT ||
121
+ env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ||
122
+ env.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT);
123
+ }
124
+ /** Build a per-signal URL from the --otel-endpoint base (env is handled by the exporter). */
125
+ function signalUrl(base, suffix) {
126
+ if (!base)
127
+ return undefined;
128
+ return `${base.replace(/\/+$/, "")}/${suffix}`;
129
+ }
130
+ async function withTimeout(promise, ms, onWarn) {
131
+ let timer;
132
+ const timeout = new Promise((resolve) => {
133
+ timer = setTimeout(() => {
134
+ onWarn(`telemetry: exporter flush timed out after ${ms}ms; proceeding`);
135
+ resolve();
136
+ }, ms);
137
+ timer.unref?.();
138
+ });
139
+ try {
140
+ await Promise.race([promise.then(() => undefined), timeout]);
141
+ }
142
+ finally {
143
+ if (timer)
144
+ clearTimeout(timer);
145
+ }
146
+ }
147
+ //# sourceMappingURL=sdk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdk.js","sourceRoot":"","sources":["../../src/telemetry/sdk.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Centralized OpenTelemetry attribute keys, span names, and metric names.
3
+ *
4
+ * Single source of truth so the still-evolving GenAI semantic conventions
5
+ * (`gen_ai.*`) are pinned in exactly one place. We hand-define the `gen_ai.*`
6
+ * keys as literals rather than importing them from
7
+ * `@opentelemetry/semantic-conventions/incubating`, because that incubating
8
+ * export path is unstable across minor releases — depending on the runtime
9
+ * values, not the package's export surface, keeps us insulated from churn.
10
+ */
11
+ /** Stable GenAI semantic-convention attribute keys. */
12
+ export declare const GenAI: {
13
+ readonly SYSTEM: "gen_ai.system";
14
+ readonly OPERATION_NAME: "gen_ai.operation.name";
15
+ readonly CONVERSATION_ID: "gen_ai.conversation.id";
16
+ readonly REQUEST_MODEL: "gen_ai.request.model";
17
+ readonly RESPONSE_MODEL: "gen_ai.response.model";
18
+ readonly RESPONSE_ID: "gen_ai.response.id";
19
+ readonly RESPONSE_FINISH_REASONS: "gen_ai.response.finish_reasons";
20
+ readonly USAGE_INPUT_TOKENS: "gen_ai.usage.input_tokens";
21
+ readonly USAGE_OUTPUT_TOKENS: "gen_ai.usage.output_tokens";
22
+ readonly TOOL_NAME: "gen_ai.tool.name";
23
+ readonly TOOL_CALL_ID: "gen_ai.tool.call.id";
24
+ /** Metric-only dimension: which token bucket a measurement belongs to. */
25
+ readonly TOKEN_TYPE: "gen_ai.token.type";
26
+ /** Content-gated span attributes (only set when includeContent is on). */
27
+ readonly PROMPT: "gen_ai.prompt";
28
+ readonly COMPLETION: "gen_ai.completion";
29
+ };
30
+ /**
31
+ * agentic-pi-specific attribute keys, namespaced under `agentic_pi.*` to
32
+ * avoid colliding with any future standard key. Used where no stable GenAI
33
+ * equivalent exists yet (cache tokens, cost, tool error/args/result).
34
+ */
35
+ export declare const AgenticPi: {
36
+ readonly CACHE_READ_TOKENS: "agentic_pi.usage.cache_read_tokens";
37
+ readonly CACHE_WRITE_TOKENS: "agentic_pi.usage.cache_write_tokens";
38
+ readonly COST_USD: "agentic_pi.usage.cost_usd";
39
+ readonly TOTAL_TOKENS: "agentic_pi.usage.total_tokens";
40
+ readonly TOOL_IS_ERROR: "agentic_pi.tool.is_error";
41
+ readonly TURN_INDEX: "agentic_pi.turn.index";
42
+ readonly SANDBOX_BACKEND: "agentic_pi.sandbox.backend";
43
+ /** Content-gated tool span attributes. */
44
+ readonly TOOL_ARGUMENTS: "agentic_pi.tool.arguments";
45
+ readonly TOOL_RESULT: "agentic_pi.tool.result";
46
+ };
47
+ /** Metric dimension value for {@link GenAI.TOKEN_TYPE}. */
48
+ export declare const TokenType: {
49
+ readonly INPUT: "input";
50
+ readonly OUTPUT: "output";
51
+ readonly CACHE_READ: "cache_read";
52
+ readonly CACHE_WRITE: "cache_write";
53
+ };
54
+ /** Span names. Tool/LLM names embed the tool/model per GenAI span-naming guidance. */
55
+ export declare const SpanName: {
56
+ readonly SESSION: "agentic_pi.session";
57
+ readonly TURN: "agentic_pi.turn";
58
+ readonly tool: (toolName: string) => string;
59
+ readonly llm: (model: string) => string;
60
+ };
61
+ /** Metric instrument names. */
62
+ export declare const MetricName: {
63
+ readonly LLM_TOKENS: "gen_ai.client.token.usage";
64
+ readonly LLM_DURATION: "gen_ai.client.operation.duration";
65
+ readonly COST: "agentic_pi.cost.usd";
66
+ readonly TOOL_DURATION: "agentic_pi.tool.duration";
67
+ readonly TOOL_INVOCATIONS: "agentic_pi.tool.invocations";
68
+ readonly TOOL_FAILURES: "agentic_pi.tool.failures";
69
+ readonly TURNS: "agentic_pi.turns";
70
+ };
71
+ /** Default OTEL resource service name when neither flag nor env overrides it. */
72
+ export declare const DEFAULT_SERVICE_NAME = "agentic-pi";