@yagni-app/code 1.0.8 → 1.0.9
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/README.md
CHANGED
|
@@ -208,9 +208,13 @@ prefix instead of `claude_code`:
|
|
|
208
208
|
|
|
209
209
|
Every signal carries `organization.id` (the workspace) and `user.email` (the
|
|
210
210
|
signed-in developer's account email, learned from the backend at session
|
|
211
|
-
start) so a collector can attribute sessions and spend per person.
|
|
212
|
-
`
|
|
213
|
-
|
|
211
|
+
start) so a collector can attribute sessions and spend per person. The LLM
|
|
212
|
+
span additionally declares `user.email` as a Datadog cost tag (the
|
|
213
|
+
`_dd.ml_obs.metadata` attribute, `{"_dd":{"cost_tags":["user.email"]}}`), so
|
|
214
|
+
Datadog's LLM Observability Cost page offers it under Custom Tags → Group by
|
|
215
|
+
and breaks spend down per developer. `OTEL_METRICS_INCLUDE_ACCOUNT_UUID=false`
|
|
216
|
+
drops the email, and that declaration, from all three signals. Prompt,
|
|
217
|
+
response, and tool content never export.
|
|
214
218
|
|
|
215
219
|
Nothing is exported unless you configure an endpoint. Enable it one of three
|
|
216
220
|
ways (first match wins):
|
|
@@ -56,6 +56,13 @@ export declare const ATTR_GEN_AI_CACHE_CREATION_TOKENS_LEGACY = "gen_ai.usage.ca
|
|
|
56
56
|
* Unit is NANODOLLARS (integer), not dollars: Datadog copies the value
|
|
57
57
|
* unscaled into its nanodollar cost metric. */
|
|
58
58
|
export declare const ATTR_GEN_AI_COST_ESTIMATED_TOTAL = "gen_ai.cost.estimated_total";
|
|
59
|
+
/** Datadog's OTLP escape hatch: a JSON-object string merged into the LLM
|
|
60
|
+
* Observability span's `meta.metadata`. Its `_dd.cost_tags` list is where
|
|
61
|
+
* Datadog's own SDKs declare which span tags the Cost page may group spend
|
|
62
|
+
* by (the SDK-only `cost_tags` parameter); sending the same shape here is
|
|
63
|
+
* what makes `user.email` a Group-by option on the vendor Cost page.
|
|
64
|
+
* Verified against live probe spans on 2026-09-04. */
|
|
65
|
+
export declare const ATTR_DD_LLMOBS_METADATA = "_dd.ml_obs.metadata";
|
|
59
66
|
export declare const ATTR_GEN_AI_CONVERSATION_ID = "gen_ai.conversation.id";
|
|
60
67
|
export declare const ATTR_GEN_AI_AGENT_NAME = "gen_ai.agent.name";
|
|
61
68
|
export declare const ATTR_GEN_AI_TOOL_NAME = "gen_ai.tool.name";
|
|
@@ -58,6 +58,13 @@ export const ATTR_GEN_AI_CACHE_CREATION_TOKENS_LEGACY = "gen_ai.usage.cache_crea
|
|
|
58
58
|
* Unit is NANODOLLARS (integer), not dollars: Datadog copies the value
|
|
59
59
|
* unscaled into its nanodollar cost metric. */
|
|
60
60
|
export const ATTR_GEN_AI_COST_ESTIMATED_TOTAL = "gen_ai.cost.estimated_total";
|
|
61
|
+
/** Datadog's OTLP escape hatch: a JSON-object string merged into the LLM
|
|
62
|
+
* Observability span's `meta.metadata`. Its `_dd.cost_tags` list is where
|
|
63
|
+
* Datadog's own SDKs declare which span tags the Cost page may group spend
|
|
64
|
+
* by (the SDK-only `cost_tags` parameter); sending the same shape here is
|
|
65
|
+
* what makes `user.email` a Group-by option on the vendor Cost page.
|
|
66
|
+
* Verified against live probe spans on 2026-09-04. */
|
|
67
|
+
export const ATTR_DD_LLMOBS_METADATA = "_dd.ml_obs.metadata";
|
|
61
68
|
export const ATTR_GEN_AI_CONVERSATION_ID = "gen_ai.conversation.id";
|
|
62
69
|
export const ATTR_GEN_AI_AGENT_NAME = "gen_ai.agent.name";
|
|
63
70
|
export const ATTR_GEN_AI_TOOL_NAME = "gen_ai.tool.name";
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
import { randomUUID } from "node:crypto";
|
|
21
21
|
import { context as otelContext, SpanStatusCode, trace, } from "@opentelemetry/api";
|
|
22
22
|
import { SeverityNumber } from "@opentelemetry/api-logs";
|
|
23
|
-
import { ATTR_APP_ENTRYPOINT, ATTR_APP_VERSION, ATTR_ERROR_TYPE, ATTR_GEN_AI_AGENT_NAME, ATTR_GEN_AI_CACHE_CREATION_TOKENS_LEGACY, ATTR_GEN_AI_CACHE_READ_TOKENS, ATTR_GEN_AI_CACHE_READ_TOKENS_LEGACY, ATTR_GEN_AI_CACHE_WRITE_TOKENS, ATTR_GEN_AI_CONVERSATION_ID, ATTR_GEN_AI_COST_ESTIMATED_TOTAL, ATTR_GEN_AI_FINISH_REASONS, ATTR_GEN_AI_INPUT_TOKENS, ATTR_GEN_AI_OPERATION_NAME, ATTR_GEN_AI_OUTPUT_TOKENS, ATTR_GEN_AI_TOTAL_TOKENS, ATTR_GEN_AI_PROVIDER_NAME, ATTR_GEN_AI_REQUEST_MODEL, ATTR_GEN_AI_RESPONSE_ID, ATTR_GEN_AI_RESPONSE_MODEL, ATTR_GEN_AI_SYSTEM, ATTR_GEN_AI_TOOL_CALL_ID, ATTR_GEN_AI_TOOL_NAME, ATTR_GEN_AI_TOOL_TYPE, ATTR_HTTP_STATUS_CODE, ATTR_ORGANIZATION_ID, ATTR_SESSION_ID, ATTR_TERMINAL_TYPE, ATTR_USER_EMAIL, EVENT_API_ERROR, EVENT_API_REQUEST, EVENT_ASSISTANT_RESPONSE, EVENT_PERMISSION_MODE_CHANGED, EVENT_TOOL_DECISION, EVENT_TOOL_RESULT, EVENT_USER_PROMPT, GEN_AI_PROVIDER, languageFromPath, METRIC_ACTIVE_TIME, METRIC_CODE_EDIT_DECISION, METRIC_COMMIT_COUNT, METRIC_COST_USAGE, METRIC_LINES_OF_CODE, METRIC_PULL_REQUEST_COUNT, METRIC_SESSION_COUNT, METRIC_TOKEN_USAGE, PREFIX, SPAN_INTERACTION, SPAN_LLM_REQUEST, SPAN_TOOL, SPAN_TURN, } from "./attrs.js";
|
|
23
|
+
import { ATTR_APP_ENTRYPOINT, ATTR_APP_VERSION, ATTR_ERROR_TYPE, ATTR_GEN_AI_AGENT_NAME, ATTR_GEN_AI_CACHE_CREATION_TOKENS_LEGACY, ATTR_GEN_AI_CACHE_READ_TOKENS, ATTR_GEN_AI_CACHE_READ_TOKENS_LEGACY, ATTR_GEN_AI_CACHE_WRITE_TOKENS, ATTR_DD_LLMOBS_METADATA, ATTR_GEN_AI_CONVERSATION_ID, ATTR_GEN_AI_COST_ESTIMATED_TOTAL, ATTR_GEN_AI_FINISH_REASONS, ATTR_GEN_AI_INPUT_TOKENS, ATTR_GEN_AI_OPERATION_NAME, ATTR_GEN_AI_OUTPUT_TOKENS, ATTR_GEN_AI_TOTAL_TOKENS, ATTR_GEN_AI_PROVIDER_NAME, ATTR_GEN_AI_REQUEST_MODEL, ATTR_GEN_AI_RESPONSE_ID, ATTR_GEN_AI_RESPONSE_MODEL, ATTR_GEN_AI_SYSTEM, ATTR_GEN_AI_TOOL_CALL_ID, ATTR_GEN_AI_TOOL_NAME, ATTR_GEN_AI_TOOL_TYPE, ATTR_HTTP_STATUS_CODE, ATTR_ORGANIZATION_ID, ATTR_SESSION_ID, ATTR_TERMINAL_TYPE, ATTR_USER_EMAIL, EVENT_API_ERROR, EVENT_API_REQUEST, EVENT_ASSISTANT_RESPONSE, EVENT_PERMISSION_MODE_CHANGED, EVENT_TOOL_DECISION, EVENT_TOOL_RESULT, EVENT_USER_PROMPT, GEN_AI_PROVIDER, languageFromPath, METRIC_ACTIVE_TIME, METRIC_CODE_EDIT_DECISION, METRIC_COMMIT_COUNT, METRIC_COST_USAGE, METRIC_LINES_OF_CODE, METRIC_PULL_REQUEST_COUNT, METRIC_SESSION_COUNT, METRIC_TOKEN_USAGE, PREFIX, SPAN_INTERACTION, SPAN_LLM_REQUEST, SPAN_TOOL, SPAN_TURN, } from "./attrs.js";
|
|
24
24
|
/** Idle cutoff for user active time: gaps longer than this are not "active". */
|
|
25
25
|
export const USER_ACTIVE_IDLE_CUTOFF_MS = 5 * 60 * 1000;
|
|
26
26
|
const EDIT_TOOLS = new Set(["edit", "write", "multi_edit", "notebook_edit"]);
|
|
@@ -238,6 +238,13 @@ export class SessionTelemetry {
|
|
|
238
238
|
attrs[ATTR_GEN_AI_REQUEST_MODEL] = model;
|
|
239
239
|
attrs.model = model;
|
|
240
240
|
}
|
|
241
|
+
// Declare `user.email` as a cost-breakdown tag for Datadog's Cost page.
|
|
242
|
+
// Only when the tag is actually on the span (same account gate): Datadog
|
|
243
|
+
// skips entries that reference a missing tag, but an empty declaration
|
|
244
|
+
// is noise. Bounded cardinality by construction: one value per seat.
|
|
245
|
+
if (ATTR_USER_EMAIL in attrs) {
|
|
246
|
+
attrs[ATTR_DD_LLMOBS_METADATA] = JSON.stringify({ _dd: { cost_tags: [ATTR_USER_EMAIL] } });
|
|
247
|
+
}
|
|
241
248
|
const span = this.tracer.startSpan(SPAN_LLM_REQUEST, { attributes: attrs }, parent);
|
|
242
249
|
this.llm = {
|
|
243
250
|
span,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yagni-app/code",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.9",
|
|
4
4
|
"description": "YAGNI Code: a terminal coding agent that already knows your company. One YAGNI login routes the model and grounds the agent in your team's context.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
6
6
|
"author": "YAGNI, Inc. <jack@yagni.app> (https://yagni.app)",
|
|
@@ -58,5 +58,5 @@
|
|
|
58
58
|
"turndown": "^7.2.4",
|
|
59
59
|
"typebox": "^1.3.15"
|
|
60
60
|
},
|
|
61
|
-
"yagniSourceSha": "
|
|
61
|
+
"yagniSourceSha": "fbd1d838bd6701d0e8135e415210ca1974bc4269"
|
|
62
62
|
}
|