@kontourai/console-telemetry 0.1.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/dist/client.d.ts +16 -0
- package/dist/client.js +31 -0
- package/dist/default-registry.d.ts +2 -0
- package/dist/default-registry.js +36 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +27 -0
- package/dist/otel.d.ts +19 -0
- package/dist/otel.js +66 -0
- package/dist/pricing.d.ts +13 -0
- package/dist/pricing.js +103 -0
- package/dist/types.d.ts +53 -0
- package/dist/types.js +8 -0
- package/package.json +38 -0
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { PricingRegistry } from "./types";
|
|
2
|
+
export interface TelemetryClientOptions {
|
|
3
|
+
/** Console base URL, e.g. https://console.example.com */
|
|
4
|
+
baseUrl: string;
|
|
5
|
+
/** Optional bearer token / tenant headers. */
|
|
6
|
+
headers?: Record<string, string>;
|
|
7
|
+
}
|
|
8
|
+
export declare class ConsoleTelemetryClient {
|
|
9
|
+
private readonly baseUrl;
|
|
10
|
+
private readonly headers;
|
|
11
|
+
constructor(options: TelemetryClientOptions);
|
|
12
|
+
/** POST one or more telemetry records to the console intake. */
|
|
13
|
+
postTelemetry(records: unknown[]): Promise<Response>;
|
|
14
|
+
/** Fetch the live pricing registry served by the console. */
|
|
15
|
+
getPricing(): Promise<PricingRegistry>;
|
|
16
|
+
}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// client.ts — typed clients for the console telemetry/pricing intake URLs.
|
|
3
|
+
//
|
|
4
|
+
// The console is the distribution hub; this is the typed surface for its URLs,
|
|
5
|
+
// shared by producers (post events / fetch pricing) and tooling.
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.ConsoleTelemetryClient = void 0;
|
|
8
|
+
class ConsoleTelemetryClient {
|
|
9
|
+
baseUrl;
|
|
10
|
+
headers;
|
|
11
|
+
constructor(options) {
|
|
12
|
+
this.baseUrl = options.baseUrl.replace(/\/+$/, "");
|
|
13
|
+
this.headers = { "content-type": "application/json", ...(options.headers || {}) };
|
|
14
|
+
}
|
|
15
|
+
/** POST one or more telemetry records to the console intake. */
|
|
16
|
+
async postTelemetry(records) {
|
|
17
|
+
return fetch(`${this.baseUrl}/api/telemetry/records`, {
|
|
18
|
+
method: "POST",
|
|
19
|
+
headers: this.headers,
|
|
20
|
+
body: JSON.stringify(records.length === 1 ? records[0] : records)
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
/** Fetch the live pricing registry served by the console. */
|
|
24
|
+
async getPricing() {
|
|
25
|
+
const res = await fetch(`${this.baseUrl}/api/telemetry/pricing`, { headers: this.headers });
|
|
26
|
+
if (!res.ok)
|
|
27
|
+
throw new Error(`pricing fetch failed: ${res.status}`);
|
|
28
|
+
return (await res.json());
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.ConsoleTelemetryClient = ConsoleTelemetryClient;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// default-registry.ts — bundled offline fallback pricing registry.
|
|
3
|
+
//
|
|
4
|
+
// This is the compiled-in snapshot used when no live registry is configured
|
|
5
|
+
// (TELEMETRY_PRICING_FILE / TELEMETRY_PRICING_URL). Keep in sync with the
|
|
6
|
+
// authored source: flow-agents/scripts/telemetry/pricing.json. The live source
|
|
7
|
+
// (file or URL) overrides this at runtime, so this only matters air-gapped.
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.DEFAULT_REGISTRY = void 0;
|
|
10
|
+
exports.DEFAULT_REGISTRY = {
|
|
11
|
+
schema_version: "2.0",
|
|
12
|
+
current_version: "2026-06-28",
|
|
13
|
+
source: "Anthropic public list pricing; cache multipliers per prompt-caching docs",
|
|
14
|
+
versions: {
|
|
15
|
+
"2026-06-28": {
|
|
16
|
+
effective_date: "2026-06-28",
|
|
17
|
+
currency: "USD",
|
|
18
|
+
unit: "per_1m_tokens",
|
|
19
|
+
cache_multipliers: { write_5m: 1.25, write_1h: 2.0, read: 0.1 },
|
|
20
|
+
models: {
|
|
21
|
+
"claude-fable-5": { input: 10.0, output: 50.0 },
|
|
22
|
+
"claude-mythos-5": { input: 10.0, output: 50.0 },
|
|
23
|
+
"claude-opus-4-8": { input: 5.0, output: 25.0 },
|
|
24
|
+
"claude-opus-4-7": { input: 5.0, output: 25.0 },
|
|
25
|
+
"claude-opus-4-6": { input: 5.0, output: 25.0 },
|
|
26
|
+
"claude-opus-4-5": { input: 5.0, output: 25.0 },
|
|
27
|
+
"claude-opus-4-1": { input: 15.0, output: 75.0 },
|
|
28
|
+
"claude-sonnet-4-6": { input: 3.0, output: 15.0 },
|
|
29
|
+
"claude-sonnet-4-5": { input: 3.0, output: 15.0 },
|
|
30
|
+
"claude-haiku-4-5": { input: 1.0, output: 5.0 }
|
|
31
|
+
},
|
|
32
|
+
default: { input: 5.0, output: 25.0 },
|
|
33
|
+
zero_cost_models: ["<synthetic>", "synthetic", "unknown", ""]
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type { TokenCounts, TelemetryUsageTotals, TelemetryUsageBreakdown, CanonicalUsage, ModelRate, PricingCacheMultipliers, PricingVersionBlock, PricingRegistry } from "./types";
|
|
2
|
+
export { DEFAULT_REGISTRY } from "./default-registry";
|
|
3
|
+
export { refreshPricingFromUrl, setRegistry, getRegistry, currentPricingVersion, listPricingVersions, costForModel } from "./pricing";
|
|
4
|
+
export { GEN_AI_SYSTEM, GEN_AI_REQUEST_MODEL, GEN_AI_RESPONSE_MODEL, GEN_AI_OPERATION_NAME, GEN_AI_USAGE_INPUT_TOKENS, GEN_AI_USAGE_OUTPUT_TOKENS, KONTOUR_CACHE_READ_TOKENS, KONTOUR_CACHE_CREATION_TOKENS, KONTOUR_COST_USD, KONTOUR_PRICING_VERSION, toOtelGenAIAttributes, fromOtelGenAIAttributes } from "./otel";
|
|
5
|
+
export type { OtelAttributes } from "./otel";
|
|
6
|
+
export { ConsoleTelemetryClient } from "./client";
|
|
7
|
+
export type { TelemetryClientOptions } from "./client";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ConsoleTelemetryClient = exports.fromOtelGenAIAttributes = exports.toOtelGenAIAttributes = exports.KONTOUR_PRICING_VERSION = exports.KONTOUR_COST_USD = exports.KONTOUR_CACHE_CREATION_TOKENS = exports.KONTOUR_CACHE_READ_TOKENS = exports.GEN_AI_USAGE_OUTPUT_TOKENS = exports.GEN_AI_USAGE_INPUT_TOKENS = exports.GEN_AI_OPERATION_NAME = exports.GEN_AI_RESPONSE_MODEL = exports.GEN_AI_REQUEST_MODEL = exports.GEN_AI_SYSTEM = exports.costForModel = exports.listPricingVersions = exports.currentPricingVersion = exports.getRegistry = exports.setRegistry = exports.refreshPricingFromUrl = exports.DEFAULT_REGISTRY = void 0;
|
|
4
|
+
var default_registry_1 = require("./default-registry");
|
|
5
|
+
Object.defineProperty(exports, "DEFAULT_REGISTRY", { enumerable: true, get: function () { return default_registry_1.DEFAULT_REGISTRY; } });
|
|
6
|
+
var pricing_1 = require("./pricing");
|
|
7
|
+
Object.defineProperty(exports, "refreshPricingFromUrl", { enumerable: true, get: function () { return pricing_1.refreshPricingFromUrl; } });
|
|
8
|
+
Object.defineProperty(exports, "setRegistry", { enumerable: true, get: function () { return pricing_1.setRegistry; } });
|
|
9
|
+
Object.defineProperty(exports, "getRegistry", { enumerable: true, get: function () { return pricing_1.getRegistry; } });
|
|
10
|
+
Object.defineProperty(exports, "currentPricingVersion", { enumerable: true, get: function () { return pricing_1.currentPricingVersion; } });
|
|
11
|
+
Object.defineProperty(exports, "listPricingVersions", { enumerable: true, get: function () { return pricing_1.listPricingVersions; } });
|
|
12
|
+
Object.defineProperty(exports, "costForModel", { enumerable: true, get: function () { return pricing_1.costForModel; } });
|
|
13
|
+
var otel_1 = require("./otel");
|
|
14
|
+
Object.defineProperty(exports, "GEN_AI_SYSTEM", { enumerable: true, get: function () { return otel_1.GEN_AI_SYSTEM; } });
|
|
15
|
+
Object.defineProperty(exports, "GEN_AI_REQUEST_MODEL", { enumerable: true, get: function () { return otel_1.GEN_AI_REQUEST_MODEL; } });
|
|
16
|
+
Object.defineProperty(exports, "GEN_AI_RESPONSE_MODEL", { enumerable: true, get: function () { return otel_1.GEN_AI_RESPONSE_MODEL; } });
|
|
17
|
+
Object.defineProperty(exports, "GEN_AI_OPERATION_NAME", { enumerable: true, get: function () { return otel_1.GEN_AI_OPERATION_NAME; } });
|
|
18
|
+
Object.defineProperty(exports, "GEN_AI_USAGE_INPUT_TOKENS", { enumerable: true, get: function () { return otel_1.GEN_AI_USAGE_INPUT_TOKENS; } });
|
|
19
|
+
Object.defineProperty(exports, "GEN_AI_USAGE_OUTPUT_TOKENS", { enumerable: true, get: function () { return otel_1.GEN_AI_USAGE_OUTPUT_TOKENS; } });
|
|
20
|
+
Object.defineProperty(exports, "KONTOUR_CACHE_READ_TOKENS", { enumerable: true, get: function () { return otel_1.KONTOUR_CACHE_READ_TOKENS; } });
|
|
21
|
+
Object.defineProperty(exports, "KONTOUR_CACHE_CREATION_TOKENS", { enumerable: true, get: function () { return otel_1.KONTOUR_CACHE_CREATION_TOKENS; } });
|
|
22
|
+
Object.defineProperty(exports, "KONTOUR_COST_USD", { enumerable: true, get: function () { return otel_1.KONTOUR_COST_USD; } });
|
|
23
|
+
Object.defineProperty(exports, "KONTOUR_PRICING_VERSION", { enumerable: true, get: function () { return otel_1.KONTOUR_PRICING_VERSION; } });
|
|
24
|
+
Object.defineProperty(exports, "toOtelGenAIAttributes", { enumerable: true, get: function () { return otel_1.toOtelGenAIAttributes; } });
|
|
25
|
+
Object.defineProperty(exports, "fromOtelGenAIAttributes", { enumerable: true, get: function () { return otel_1.fromOtelGenAIAttributes; } });
|
|
26
|
+
var client_1 = require("./client");
|
|
27
|
+
Object.defineProperty(exports, "ConsoleTelemetryClient", { enumerable: true, get: function () { return client_1.ConsoleTelemetryClient; } });
|
package/dist/otel.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { CanonicalUsage } from "./types";
|
|
2
|
+
export declare const GEN_AI_SYSTEM = "gen_ai.system";
|
|
3
|
+
export declare const GEN_AI_REQUEST_MODEL = "gen_ai.request.model";
|
|
4
|
+
export declare const GEN_AI_RESPONSE_MODEL = "gen_ai.response.model";
|
|
5
|
+
export declare const GEN_AI_OPERATION_NAME = "gen_ai.operation.name";
|
|
6
|
+
export declare const GEN_AI_USAGE_INPUT_TOKENS = "gen_ai.usage.input_tokens";
|
|
7
|
+
export declare const GEN_AI_USAGE_OUTPUT_TOKENS = "gen_ai.usage.output_tokens";
|
|
8
|
+
export declare const KONTOUR_CACHE_READ_TOKENS = "gen_ai.usage.cache_read_input_tokens";
|
|
9
|
+
export declare const KONTOUR_CACHE_CREATION_TOKENS = "gen_ai.usage.cache_creation_input_tokens";
|
|
10
|
+
export declare const KONTOUR_COST_USD = "kontour.gen_ai.usage.cost_usd";
|
|
11
|
+
export declare const KONTOUR_PRICING_VERSION = "kontour.gen_ai.pricing_version";
|
|
12
|
+
export type OtelAttributes = Record<string, string | number | boolean>;
|
|
13
|
+
/**
|
|
14
|
+
* Map a canonical usage block to OTel GenAI attributes. `system` is the runtime
|
|
15
|
+
* (e.g. "claude-code", "strands"). Cache tokens + cost ride as extension keys.
|
|
16
|
+
*/
|
|
17
|
+
export declare function toOtelGenAIAttributes(usage: CanonicalUsage, system?: string): OtelAttributes;
|
|
18
|
+
/** Inverse: read a canonical usage block from OTel GenAI attributes (ingest interop). */
|
|
19
|
+
export declare function fromOtelGenAIAttributes(attrs: OtelAttributes): CanonicalUsage;
|
package/dist/otel.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// otel.ts — OpenTelemetry GenAI semantic-conventions mapping.
|
|
3
|
+
//
|
|
4
|
+
// Speak the standard at the boundary, keep the richer canonical model inside.
|
|
5
|
+
// Core GenAI attributes (gen_ai.system, gen_ai.request.model,
|
|
6
|
+
// gen_ai.usage.input_tokens/output_tokens) are stable; the broader GenAI
|
|
7
|
+
// semconv is still experimental (Development status) as of 2026, so we map
|
|
8
|
+
// conservatively. Cache tokens + cost are NOT in the standard — emitted as
|
|
9
|
+
// clearly-namespaced extension attributes.
|
|
10
|
+
// Ref: https://opentelemetry.io/docs/specs/semconv/registry/attributes/gen-ai/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.KONTOUR_PRICING_VERSION = exports.KONTOUR_COST_USD = exports.KONTOUR_CACHE_CREATION_TOKENS = exports.KONTOUR_CACHE_READ_TOKENS = exports.GEN_AI_USAGE_OUTPUT_TOKENS = exports.GEN_AI_USAGE_INPUT_TOKENS = exports.GEN_AI_OPERATION_NAME = exports.GEN_AI_RESPONSE_MODEL = exports.GEN_AI_REQUEST_MODEL = exports.GEN_AI_SYSTEM = void 0;
|
|
13
|
+
exports.toOtelGenAIAttributes = toOtelGenAIAttributes;
|
|
14
|
+
exports.fromOtelGenAIAttributes = fromOtelGenAIAttributes;
|
|
15
|
+
// Stable / core GenAI attributes
|
|
16
|
+
exports.GEN_AI_SYSTEM = "gen_ai.system";
|
|
17
|
+
exports.GEN_AI_REQUEST_MODEL = "gen_ai.request.model";
|
|
18
|
+
exports.GEN_AI_RESPONSE_MODEL = "gen_ai.response.model";
|
|
19
|
+
exports.GEN_AI_OPERATION_NAME = "gen_ai.operation.name";
|
|
20
|
+
exports.GEN_AI_USAGE_INPUT_TOKENS = "gen_ai.usage.input_tokens";
|
|
21
|
+
exports.GEN_AI_USAGE_OUTPUT_TOKENS = "gen_ai.usage.output_tokens";
|
|
22
|
+
// Extension attributes (NOT in the GenAI semconv — Anthropic cache + cost).
|
|
23
|
+
exports.KONTOUR_CACHE_READ_TOKENS = "gen_ai.usage.cache_read_input_tokens";
|
|
24
|
+
exports.KONTOUR_CACHE_CREATION_TOKENS = "gen_ai.usage.cache_creation_input_tokens";
|
|
25
|
+
exports.KONTOUR_COST_USD = "kontour.gen_ai.usage.cost_usd";
|
|
26
|
+
exports.KONTOUR_PRICING_VERSION = "kontour.gen_ai.pricing_version";
|
|
27
|
+
function n(v) {
|
|
28
|
+
return typeof v === "number" && Number.isFinite(v) ? v : 0;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Map a canonical usage block to OTel GenAI attributes. `system` is the runtime
|
|
32
|
+
* (e.g. "claude-code", "strands"). Cache tokens + cost ride as extension keys.
|
|
33
|
+
*/
|
|
34
|
+
function toOtelGenAIAttributes(usage, system) {
|
|
35
|
+
const attrs = {};
|
|
36
|
+
if (system)
|
|
37
|
+
attrs[exports.GEN_AI_SYSTEM] = system;
|
|
38
|
+
if (usage.model) {
|
|
39
|
+
attrs[exports.GEN_AI_REQUEST_MODEL] = usage.model;
|
|
40
|
+
attrs[exports.GEN_AI_RESPONSE_MODEL] = usage.model;
|
|
41
|
+
}
|
|
42
|
+
attrs[exports.GEN_AI_OPERATION_NAME] = "chat";
|
|
43
|
+
attrs[exports.GEN_AI_USAGE_INPUT_TOKENS] = n(usage.inputTokens);
|
|
44
|
+
attrs[exports.GEN_AI_USAGE_OUTPUT_TOKENS] = n(usage.outputTokens);
|
|
45
|
+
attrs[exports.KONTOUR_CACHE_READ_TOKENS] = n(usage.cacheReadInputTokens);
|
|
46
|
+
attrs[exports.KONTOUR_CACHE_CREATION_TOKENS] = n(usage.cacheCreationInputTokens);
|
|
47
|
+
if (typeof usage.estimatedCostUsd === "number")
|
|
48
|
+
attrs[exports.KONTOUR_COST_USD] = usage.estimatedCostUsd;
|
|
49
|
+
if (usage.pricingVersion)
|
|
50
|
+
attrs[exports.KONTOUR_PRICING_VERSION] = usage.pricingVersion;
|
|
51
|
+
return attrs;
|
|
52
|
+
}
|
|
53
|
+
/** Inverse: read a canonical usage block from OTel GenAI attributes (ingest interop). */
|
|
54
|
+
function fromOtelGenAIAttributes(attrs) {
|
|
55
|
+
const num = (k) => (typeof attrs[k] === "number" ? attrs[k] : 0);
|
|
56
|
+
const str = (k) => (typeof attrs[k] === "string" ? attrs[k] : undefined);
|
|
57
|
+
return {
|
|
58
|
+
model: str(exports.GEN_AI_RESPONSE_MODEL) || str(exports.GEN_AI_REQUEST_MODEL),
|
|
59
|
+
inputTokens: num(exports.GEN_AI_USAGE_INPUT_TOKENS),
|
|
60
|
+
outputTokens: num(exports.GEN_AI_USAGE_OUTPUT_TOKENS),
|
|
61
|
+
cacheReadInputTokens: num(exports.KONTOUR_CACHE_READ_TOKENS),
|
|
62
|
+
cacheCreationInputTokens: num(exports.KONTOUR_CACHE_CREATION_TOKENS),
|
|
63
|
+
estimatedCostUsd: typeof attrs[exports.KONTOUR_COST_USD] === "number" ? attrs[exports.KONTOUR_COST_USD] : undefined,
|
|
64
|
+
pricingVersion: str(exports.KONTOUR_PRICING_VERSION)
|
|
65
|
+
};
|
|
66
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { PricingRegistry, TokenCounts } from "./types";
|
|
2
|
+
/** Replace the in-memory registry from a remote URL (single live source). */
|
|
3
|
+
export declare function refreshPricingFromUrl(url?: string | undefined): Promise<boolean>;
|
|
4
|
+
/** Replace the in-memory registry directly (e.g. console syncing from flow-agents). */
|
|
5
|
+
export declare function setRegistry(registry: PricingRegistry): boolean;
|
|
6
|
+
export declare function getRegistry(): PricingRegistry;
|
|
7
|
+
export declare function currentPricingVersion(): string;
|
|
8
|
+
export declare function listPricingVersions(): string[];
|
|
9
|
+
/**
|
|
10
|
+
* Estimated USD cost for one model's token counts, priced against the given
|
|
11
|
+
* registry version (defaults to current). Cache writes assume the 5m TTL tier.
|
|
12
|
+
*/
|
|
13
|
+
export declare function costForModel(model: string | undefined, tokens: TokenCounts, version?: string): number;
|
package/dist/pricing.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// pricing.ts — versioned pricing registry loader + cost recompute.
|
|
3
|
+
//
|
|
4
|
+
// Single source of truth for cost math. Resolution (init, synchronous):
|
|
5
|
+
// 1. local file TELEMETRY_PRICING_FILE / FLOW_AGENTS_PRICING_FILE
|
|
6
|
+
// 2. bundled DEFAULT_REGISTRY
|
|
7
|
+
// Remote (TELEMETRY_PRICING_URL) is applied via async refreshPricingFromUrl()
|
|
8
|
+
// — call it at server boot / on an interval. Tokens are the source of truth;
|
|
9
|
+
// cost is derived here against an explicit version (defaults to current), so a
|
|
10
|
+
// session priced at emit can be reproduced or recomputed against any version.
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.refreshPricingFromUrl = refreshPricingFromUrl;
|
|
13
|
+
exports.setRegistry = setRegistry;
|
|
14
|
+
exports.getRegistry = getRegistry;
|
|
15
|
+
exports.currentPricingVersion = currentPricingVersion;
|
|
16
|
+
exports.listPricingVersions = listPricingVersions;
|
|
17
|
+
exports.costForModel = costForModel;
|
|
18
|
+
const fs = require("node:fs");
|
|
19
|
+
const default_registry_1 = require("./default-registry");
|
|
20
|
+
function isRegistry(value) {
|
|
21
|
+
return Boolean(value &&
|
|
22
|
+
typeof value === "object" &&
|
|
23
|
+
typeof value.current_version === "string" &&
|
|
24
|
+
value.versions &&
|
|
25
|
+
typeof value.versions === "object");
|
|
26
|
+
}
|
|
27
|
+
function loadRegistrySync() {
|
|
28
|
+
const envPath = process.env.TELEMETRY_PRICING_FILE || process.env.FLOW_AGENTS_PRICING_FILE;
|
|
29
|
+
if (envPath) {
|
|
30
|
+
try {
|
|
31
|
+
const parsed = JSON.parse(fs.readFileSync(envPath, "utf8"));
|
|
32
|
+
if (isRegistry(parsed))
|
|
33
|
+
return parsed;
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
// fall through to bundled
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return default_registry_1.DEFAULT_REGISTRY;
|
|
40
|
+
}
|
|
41
|
+
let REGISTRY = loadRegistrySync();
|
|
42
|
+
/** Replace the in-memory registry from a remote URL (single live source). */
|
|
43
|
+
async function refreshPricingFromUrl(url = process.env.TELEMETRY_PRICING_URL || process.env.FLOW_AGENTS_PRICING_URL) {
|
|
44
|
+
if (!url)
|
|
45
|
+
return false;
|
|
46
|
+
try {
|
|
47
|
+
const res = await fetch(url);
|
|
48
|
+
if (!res.ok)
|
|
49
|
+
return false;
|
|
50
|
+
const parsed = await res.json();
|
|
51
|
+
if (isRegistry(parsed)) {
|
|
52
|
+
REGISTRY = parsed;
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// keep current registry on any failure
|
|
58
|
+
}
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
/** Replace the in-memory registry directly (e.g. console syncing from flow-agents). */
|
|
62
|
+
function setRegistry(registry) {
|
|
63
|
+
if (!isRegistry(registry))
|
|
64
|
+
return false;
|
|
65
|
+
REGISTRY = registry;
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
function getRegistry() {
|
|
69
|
+
return REGISTRY;
|
|
70
|
+
}
|
|
71
|
+
function currentPricingVersion() {
|
|
72
|
+
return REGISTRY.current_version;
|
|
73
|
+
}
|
|
74
|
+
function listPricingVersions() {
|
|
75
|
+
return Object.keys(REGISTRY.versions || {});
|
|
76
|
+
}
|
|
77
|
+
function versionBlock(version) {
|
|
78
|
+
const versions = REGISTRY.versions || {};
|
|
79
|
+
return (versions[version || REGISTRY.current_version] ||
|
|
80
|
+
versions[REGISTRY.current_version] ||
|
|
81
|
+
default_registry_1.DEFAULT_REGISTRY.versions[default_registry_1.DEFAULT_REGISTRY.current_version]);
|
|
82
|
+
}
|
|
83
|
+
function round6(value) {
|
|
84
|
+
return Math.round(value * 1_000_000) / 1_000_000;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Estimated USD cost for one model's token counts, priced against the given
|
|
88
|
+
* registry version (defaults to current). Cache writes assume the 5m TTL tier.
|
|
89
|
+
*/
|
|
90
|
+
function costForModel(model, tokens, version) {
|
|
91
|
+
const block = versionBlock(version);
|
|
92
|
+
const key = (model || "").trim();
|
|
93
|
+
if (block.zero_cost_models.includes(key))
|
|
94
|
+
return 0;
|
|
95
|
+
const rate = block.models[key] || block.default;
|
|
96
|
+
const cm = block.cache_multipliers;
|
|
97
|
+
const cost = (tokens.inputTokens * rate.input +
|
|
98
|
+
tokens.outputTokens * rate.output +
|
|
99
|
+
tokens.cacheCreationInputTokens * rate.input * cm.write_5m +
|
|
100
|
+
tokens.cacheReadInputTokens * rate.input * cm.read) /
|
|
101
|
+
1_000_000;
|
|
102
|
+
return round6(cost);
|
|
103
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export interface TokenCounts {
|
|
2
|
+
inputTokens: number;
|
|
3
|
+
outputTokens: number;
|
|
4
|
+
cacheCreationInputTokens: number;
|
|
5
|
+
cacheReadInputTokens: number;
|
|
6
|
+
}
|
|
7
|
+
export interface TelemetryUsageTotals extends TokenCounts {
|
|
8
|
+
totalTokens: number;
|
|
9
|
+
estimatedCostUsd: number;
|
|
10
|
+
}
|
|
11
|
+
export interface TelemetryUsageBreakdown extends TelemetryUsageTotals {
|
|
12
|
+
key: string;
|
|
13
|
+
label: string;
|
|
14
|
+
}
|
|
15
|
+
/** The `usage` block carried by a `session.usage` telemetry event. */
|
|
16
|
+
export interface CanonicalUsage {
|
|
17
|
+
model?: string;
|
|
18
|
+
durationS?: number | null;
|
|
19
|
+
inputTokens?: number;
|
|
20
|
+
outputTokens?: number;
|
|
21
|
+
cacheCreationInputTokens?: number;
|
|
22
|
+
cacheReadInputTokens?: number;
|
|
23
|
+
estimatedCostUsd?: number;
|
|
24
|
+
pricingVersion?: string;
|
|
25
|
+
byModel?: Array<TokenCounts & {
|
|
26
|
+
model: string;
|
|
27
|
+
estimatedCostUsd?: number;
|
|
28
|
+
}>;
|
|
29
|
+
}
|
|
30
|
+
export interface ModelRate {
|
|
31
|
+
input: number;
|
|
32
|
+
output: number;
|
|
33
|
+
}
|
|
34
|
+
export interface PricingCacheMultipliers {
|
|
35
|
+
write_5m: number;
|
|
36
|
+
write_1h: number;
|
|
37
|
+
read: number;
|
|
38
|
+
}
|
|
39
|
+
export interface PricingVersionBlock {
|
|
40
|
+
effective_date?: string;
|
|
41
|
+
currency?: string;
|
|
42
|
+
unit?: string;
|
|
43
|
+
cache_multipliers: PricingCacheMultipliers;
|
|
44
|
+
models: Record<string, ModelRate>;
|
|
45
|
+
default: ModelRate;
|
|
46
|
+
zero_cost_models: string[];
|
|
47
|
+
}
|
|
48
|
+
export interface PricingRegistry {
|
|
49
|
+
schema_version?: string;
|
|
50
|
+
current_version: string;
|
|
51
|
+
source?: string;
|
|
52
|
+
versions: Record<string, PricingVersionBlock>;
|
|
53
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// types.ts — canonical telemetry + pricing contract shapes.
|
|
3
|
+
//
|
|
4
|
+
// One definition consumed by the console server (ingest/aggregation) and by
|
|
5
|
+
// producers (flow-agents runtimes/sinks). Pricing has no industry standard, so
|
|
6
|
+
// this is the controlled shape; telemetry maps to OpenTelemetry GenAI semconv
|
|
7
|
+
// at the boundary (see otel.ts).
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kontourai/console-telemetry",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "commonjs",
|
|
5
|
+
"exports": {
|
|
6
|
+
".": {
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"default": "./dist/index.js"
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"test": "node --import tsx --test test/*.ts",
|
|
13
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
14
|
+
"build": "tsc -p tsconfig.build.json",
|
|
15
|
+
"prepack": "npm run build",
|
|
16
|
+
"prepare": "npm run build"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@types/node": "^25.9.1",
|
|
20
|
+
"tsx": "^4.22.4",
|
|
21
|
+
"typescript": "^6.0.3"
|
|
22
|
+
},
|
|
23
|
+
"description": "Canonical Kontour Console telemetry contract: event + pricing shapes, versioned pricing registry, OpenTelemetry GenAI mapping, and intake/pricing clients.",
|
|
24
|
+
"license": "Apache-2.0",
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "git+https://github.com/kontourai/console.git",
|
|
28
|
+
"directory": "console-telemetry"
|
|
29
|
+
},
|
|
30
|
+
"main": "dist/index.js",
|
|
31
|
+
"types": "dist/index.d.ts",
|
|
32
|
+
"files": [
|
|
33
|
+
"dist"
|
|
34
|
+
],
|
|
35
|
+
"publishConfig": {
|
|
36
|
+
"access": "public"
|
|
37
|
+
}
|
|
38
|
+
}
|