@gajae-code/agent-core 0.3.0 → 0.3.1

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 CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.3.1] - 2026-06-05
6
+
7
+ ### Fixed
8
+
9
+ - Moved the env-driven full message content capture warning into agent-core telemetry resolution so direct `@gajae-code/agent-core` consumers receive `full_content_capture_env_active` when `OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=full` is used without an explicit `captureMessageContent` override.
10
+
11
+ ### Changed
12
+
13
+ - Clarified that telemetry `summary` content capture emits bounded real-content snippets in `pi.gen_ai.*` attributes and is not redacted or PII-free.
14
+
5
15
  ## [0.2.4] - 2026-06-02
6
16
 
7
17
  ### Added
@@ -211,8 +211,9 @@ export interface AgentIdentity {
211
211
  readonly name?: string;
212
212
  readonly description?: string;
213
213
  }
214
+ export type AgentTelemetryWarningCode = "resolve_attributes_failed" | "content_serializer_failed" | "on_cost_delta_failed" | "on_chat_usage_failed" | "cost_estimator_failed" | "on_run_end_failed" | "on_span_start_failed" | "on_span_end_failed" | "normalize_agent_name_failed" | "normalize_provider_failed" | "full_content_capture_env_active" | "on_telemetry_warning_failed";
214
215
  export interface AgentTelemetryWarning {
215
- readonly code: "resolve_attributes_failed" | "content_serializer_failed" | "on_cost_delta_failed" | "on_chat_usage_failed" | "cost_estimator_failed" | "on_run_end_failed" | "on_span_start_failed" | "on_span_end_failed" | "normalize_agent_name_failed" | "normalize_provider_failed" | "on_telemetry_warning_failed";
216
+ readonly code: AgentTelemetryWarningCode;
216
217
  readonly message: string;
217
218
  readonly error?: unknown;
218
219
  }
@@ -249,12 +250,18 @@ export interface AgentTelemetryConfig {
249
250
  /** Override the tracer name passed to `trace.getTracer`. */
250
251
  readonly tracerName?: string;
251
252
  /**
252
- * Capture request/response content. `true` preserves the historical full
253
- * payload capture; `"summary"` emits bounded dashboard-friendly summaries;
254
- * `"full"` emits both summaries and full OTEL message payloads.
253
+ * Capture request/response content. Programmatic `true` preserves the
254
+ * historical full payload capture because code config is an explicit opt-in;
255
+ * `"summary"` emits bounded dashboard-friendly summaries in
256
+ * `pi.gen_ai.request.messages`, `pi.gen_ai.response.text`, and related
257
+ * `pi.gen_ai.*` attributes. Summary mode is not redacted or PII-free: text is
258
+ * truncated to bounded snippets, not removed. `"full"` emits both summaries
259
+ * and full OTEL message payloads.
255
260
  *
256
261
  * Defaults to the value of the `OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT`
257
- * env var (`true`/`1`/`yes` => `"full"`, `"summary"` => `"summary"`).
262
+ * env var (`true`/`1`/`yes` => `"summary"`, `"summary"` => `"summary"`,
263
+ * `"full"` => `"full"`). Env-driven `"full"` capture emits a
264
+ * `full_content_capture_env_active` telemetry warning once per process.
258
265
  */
259
266
  readonly captureMessageContent?: TelemetryContentCapture;
260
267
  /** Extra attributes merged onto every emitted span. */
@@ -335,6 +342,7 @@ export interface AgentTelemetry {
335
342
  }
336
343
  /** Lazily resolve the {@link AgentTelemetry} handle. Returns `undefined` when disabled. */
337
344
  export declare function resolveTelemetry(config: AgentTelemetryConfig | undefined, sessionId: string | undefined): AgentTelemetry | undefined;
345
+ export declare function resetContentCaptureEnvCacheForTest(): void;
338
346
  export declare function recordTelemetryWarning(telemetry: AgentTelemetry | undefined, warning: AgentTelemetryWarning): void;
339
347
  /**
340
348
  * Start the outer `invoke_agent` span that wraps a full `runLoop` invocation.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@gajae-code/agent-core",
4
- "version": "0.3.0",
4
+ "version": "0.3.1",
5
5
  "description": "General-purpose agent with transport abstraction, state management, and attachment support",
6
6
  "homepage": "https://gaebal-gajae.dev",
7
7
  "author": "Yeachan-Heo",
@@ -35,9 +35,9 @@
35
35
  "fmt": "biome format --write ."
36
36
  },
37
37
  "dependencies": {
38
- "@gajae-code/ai": "0.3.0",
39
- "@gajae-code/natives": "0.3.0",
40
- "@gajae-code/utils": "0.3.0",
38
+ "@gajae-code/ai": "0.3.1",
39
+ "@gajae-code/natives": "0.3.1",
40
+ "@gajae-code/utils": "0.3.1",
41
41
  "@opentelemetry/api": "^1.9.0"
42
42
  },
43
43
  "devDependencies": {
package/src/telemetry.ts CHANGED
@@ -55,6 +55,9 @@ export const DEFAULT_TRACER_NAME = "@gajae-code/agent-core";
55
55
 
56
56
  /** Env var matching the OTEL semconv content-capture toggle. */
57
57
  const CONTENT_CAPTURE_ENV = "OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT";
58
+ const FULL_CONTENT_CAPTURE_ENV_WARNING =
59
+ `${CONTENT_CAPTURE_ENV}=full enables full GenAI message content capture. ` +
60
+ `Use ${CONTENT_CAPTURE_ENV}=summary for bounded telemetry summaries.`;
58
61
 
59
62
  const MAX_TELEMETRY_ARRAY_ITEMS = 64;
60
63
  const MAX_TELEMETRY_MESSAGE_COUNT = 16;
@@ -271,19 +274,22 @@ export interface AgentIdentity {
271
274
  readonly description?: string;
272
275
  }
273
276
 
277
+ export type AgentTelemetryWarningCode =
278
+ | "resolve_attributes_failed"
279
+ | "content_serializer_failed"
280
+ | "on_cost_delta_failed"
281
+ | "on_chat_usage_failed"
282
+ | "cost_estimator_failed"
283
+ | "on_run_end_failed"
284
+ | "on_span_start_failed"
285
+ | "on_span_end_failed"
286
+ | "normalize_agent_name_failed"
287
+ | "normalize_provider_failed"
288
+ | "full_content_capture_env_active"
289
+ | "on_telemetry_warning_failed";
290
+
274
291
  export interface AgentTelemetryWarning {
275
- readonly code:
276
- | "resolve_attributes_failed"
277
- | "content_serializer_failed"
278
- | "on_cost_delta_failed"
279
- | "on_chat_usage_failed"
280
- | "cost_estimator_failed"
281
- | "on_run_end_failed"
282
- | "on_span_start_failed"
283
- | "on_span_end_failed"
284
- | "normalize_agent_name_failed"
285
- | "normalize_provider_failed"
286
- | "on_telemetry_warning_failed";
292
+ readonly code: AgentTelemetryWarningCode;
287
293
  readonly message: string;
288
294
  readonly error?: unknown;
289
295
  }
@@ -322,12 +328,18 @@ export interface AgentTelemetryConfig {
322
328
  /** Override the tracer name passed to `trace.getTracer`. */
323
329
  readonly tracerName?: string;
324
330
  /**
325
- * Capture request/response content. `true` preserves the historical full
326
- * payload capture; `"summary"` emits bounded dashboard-friendly summaries;
327
- * `"full"` emits both summaries and full OTEL message payloads.
331
+ * Capture request/response content. Programmatic `true` preserves the
332
+ * historical full payload capture because code config is an explicit opt-in;
333
+ * `"summary"` emits bounded dashboard-friendly summaries in
334
+ * `pi.gen_ai.request.messages`, `pi.gen_ai.response.text`, and related
335
+ * `pi.gen_ai.*` attributes. Summary mode is not redacted or PII-free: text is
336
+ * truncated to bounded snippets, not removed. `"full"` emits both summaries
337
+ * and full OTEL message payloads.
328
338
  *
329
339
  * Defaults to the value of the `OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT`
330
- * env var (`true`/`1`/`yes` => `"full"`, `"summary"` => `"summary"`).
340
+ * env var (`true`/`1`/`yes` => `"summary"`, `"summary"` => `"summary"`,
341
+ * `"full"` => `"full"`). Env-driven `"full"` capture emits a
342
+ * `full_content_capture_env_active` telemetry warning once per process.
331
343
  */
332
344
  readonly captureMessageContent?: TelemetryContentCapture;
333
345
  /** Extra attributes merged onto every emitted span. */
@@ -415,8 +427,9 @@ export function resolveTelemetry(
415
427
  ): AgentTelemetry | undefined {
416
428
  if (!config) return undefined;
417
429
  const tracer = config.tracer ?? trace.getTracer(config.tracerName ?? DEFAULT_TRACER_NAME);
430
+ const contentCaptureFromEnv = config.captureMessageContent === undefined;
418
431
  const contentCapture = resolveContentCapture(config.captureMessageContent);
419
- return {
432
+ const telemetry = {
420
433
  config,
421
434
  tracer,
422
435
  captureMessageContent: contentCapture === "full",
@@ -425,9 +438,12 @@ export function resolveTelemetry(
425
438
  agent: config.agent,
426
439
  collector: new AgentRunCollector(),
427
440
  };
441
+ warnIfEnvFullContentCaptureActive(telemetry, contentCaptureFromEnv);
442
+ return telemetry;
428
443
  }
429
444
 
430
445
  let contentCaptureEnvCache: ResolvedTelemetryContentCapture | undefined;
446
+ let hasWarnedFullContentCaptureEnv = false;
431
447
  function readContentCaptureEnv(): ResolvedTelemetryContentCapture {
432
448
  if (contentCaptureEnvCache !== undefined) return contentCaptureEnvCache;
433
449
  const raw = process.env[CONTENT_CAPTURE_ENV];
@@ -436,15 +452,21 @@ function readContentCaptureEnv(): ResolvedTelemetryContentCapture {
436
452
  return "none";
437
453
  }
438
454
  const normalized = raw.trim().toLowerCase();
439
- if (normalized === "summary") {
455
+ if (normalized === "full") {
456
+ contentCaptureEnvCache = "full";
457
+ } else if (normalized === "summary" || normalized === "true" || normalized === "1" || normalized === "yes") {
440
458
  contentCaptureEnvCache = "summary";
441
459
  } else {
442
- contentCaptureEnvCache =
443
- normalized === "true" || normalized === "1" || normalized === "yes" || normalized === "full" ? "full" : "none";
460
+ contentCaptureEnvCache = "none";
444
461
  }
445
462
  return contentCaptureEnvCache;
446
463
  }
447
464
 
465
+ export function resetContentCaptureEnvCacheForTest(): void {
466
+ contentCaptureEnvCache = undefined;
467
+ hasWarnedFullContentCaptureEnv = false;
468
+ }
469
+
448
470
  function resolveContentCapture(value: TelemetryContentCapture | undefined): ResolvedTelemetryContentCapture {
449
471
  const capture = value ?? readContentCaptureEnv();
450
472
  if (capture === true || capture === "full") return "full";
@@ -452,6 +474,15 @@ function resolveContentCapture(value: TelemetryContentCapture | undefined): Reso
452
474
  return "none";
453
475
  }
454
476
 
477
+ function warnIfEnvFullContentCaptureActive(telemetry: AgentTelemetry, contentCaptureFromEnv: boolean): void {
478
+ if (!contentCaptureFromEnv || telemetry.contentCapture !== "full" || hasWarnedFullContentCaptureEnv) return;
479
+ hasWarnedFullContentCaptureEnv = true;
480
+ emitTelemetryWarning(telemetry, {
481
+ code: "full_content_capture_env_active",
482
+ message: FULL_CONTENT_CAPTURE_ENV_WARNING,
483
+ });
484
+ }
485
+
455
486
  /**
456
487
  * Start a span with the standard attribute envelope (provider, operation,
457
488
  * conversation, agent identity, user-supplied extras) pre-applied. Returns