@frugalco/frugal-sdk-node 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.
Files changed (59) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +227 -0
  3. package/dist/block-hash-lru.d.ts +18 -0
  4. package/dist/block-hash-lru.d.ts.map +1 -0
  5. package/dist/block-hash-lru.js +48 -0
  6. package/dist/block-hash-lru.js.map +1 -0
  7. package/dist/caller.d.ts +23 -0
  8. package/dist/caller.d.ts.map +1 -0
  9. package/dist/caller.js +204 -0
  10. package/dist/caller.js.map +1 -0
  11. package/dist/config.d.ts +21 -0
  12. package/dist/config.d.ts.map +1 -0
  13. package/dist/config.js +165 -0
  14. package/dist/config.js.map +1 -0
  15. package/dist/index.d.ts +6 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +5 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/instrument.d.ts +49 -0
  20. package/dist/instrument.d.ts.map +1 -0
  21. package/dist/instrument.js +194 -0
  22. package/dist/instrument.js.map +1 -0
  23. package/dist/otel.d.ts +27 -0
  24. package/dist/otel.d.ts.map +1 -0
  25. package/dist/otel.js +211 -0
  26. package/dist/otel.js.map +1 -0
  27. package/dist/prompt-analyzer.d.ts +26 -0
  28. package/dist/prompt-analyzer.d.ts.map +1 -0
  29. package/dist/prompt-analyzer.js +210 -0
  30. package/dist/prompt-analyzer.js.map +1 -0
  31. package/dist/semconv.d.ts +52 -0
  32. package/dist/semconv.d.ts.map +1 -0
  33. package/dist/semconv.js +53 -0
  34. package/dist/semconv.js.map +1 -0
  35. package/dist/streams.d.ts +21 -0
  36. package/dist/streams.d.ts.map +1 -0
  37. package/dist/streams.js +85 -0
  38. package/dist/streams.js.map +1 -0
  39. package/dist/track.d.ts +44 -0
  40. package/dist/track.d.ts.map +1 -0
  41. package/dist/track.js +170 -0
  42. package/dist/track.js.map +1 -0
  43. package/dist/wrappers/anthropic.d.ts +2 -0
  44. package/dist/wrappers/anthropic.d.ts.map +1 -0
  45. package/dist/wrappers/anthropic.js +229 -0
  46. package/dist/wrappers/anthropic.js.map +1 -0
  47. package/dist/wrappers/bedrock-models.d.ts +26 -0
  48. package/dist/wrappers/bedrock-models.d.ts.map +1 -0
  49. package/dist/wrappers/bedrock-models.js +320 -0
  50. package/dist/wrappers/bedrock-models.js.map +1 -0
  51. package/dist/wrappers/bedrock.d.ts +2 -0
  52. package/dist/wrappers/bedrock.d.ts.map +1 -0
  53. package/dist/wrappers/bedrock.js +284 -0
  54. package/dist/wrappers/bedrock.js.map +1 -0
  55. package/dist/wrappers/openai.d.ts +2 -0
  56. package/dist/wrappers/openai.d.ts.map +1 -0
  57. package/dist/wrappers/openai.js +347 -0
  58. package/dist/wrappers/openai.js.map +1 -0
  59. package/package.json +60 -0
package/dist/caller.js ADDED
@@ -0,0 +1,204 @@
1
+ // Stack walking to resolve the call site of a wrapped AI call.
2
+ //
3
+ // Uses V8's Error.prepareStackTrace to get structured CallSite objects rather
4
+ // than regex-parsing stack strings. Walks upward from the wrapper frame until
5
+ // we find a frame whose source file is not (a) inside our own package, (b)
6
+ // inside the wrapped SDK package, or (c) under any FRUGAL_PATH_BLOCK_LIST
7
+ // prefix. Returns the file relative to FRUGAL_REPO_ROOT plus the function
8
+ // name.
9
+ //
10
+ // Performance: realpath results and full caller resolutions are cached so the
11
+ // stack walk and path resolution only happen once per unique call site.
12
+ // Subsequent calls from the same site are a Map.get() lookup.
13
+ import { realpathSync } from "node:fs";
14
+ import { sep } from "node:path";
15
+ import { fileURLToPath } from "node:url";
16
+ import { CALLER_FILE_EXTERNAL, CALLER_FILE_UNKNOWN, CALLER_OVERFLOW, } from "./semconv.js";
17
+ const CACHE_MAX_SIZE = 10_000;
18
+ // filename → realpath
19
+ const realpathCache = new Map();
20
+ // "filename\0functionName" → CallerInfo | null (null = skip this frame)
21
+ const callerCache = new Map();
22
+ // Cardinality cap state — first-come-first-served. Once `seenCallSites` hits
23
+ // the configured max, subsequent unseen pairs overflow (partial if the file
24
+ // is already known, full otherwise).
25
+ const seenCallSites = new Set();
26
+ const seenFiles = new Set();
27
+ let capHitNotified = false;
28
+ let capHitPending = false;
29
+ export function resolveCaller(args) {
30
+ const frames = captureCallSites(args.skipFrames ?? 1);
31
+ for (const frame of frames) {
32
+ const raw = frame.getFileName();
33
+ if (!raw)
34
+ continue;
35
+ const fnName = frame.getFunctionName() ?? frame.getMethodName() ?? "<anonymous>";
36
+ // Fast path: check caller cache before any path work.
37
+ const cacheKey = raw + "\0" + fnName;
38
+ const cached = callerCache.get(cacheKey);
39
+ if (cached !== undefined) {
40
+ if (cached === null)
41
+ continue; // known skip frame
42
+ return cached;
43
+ }
44
+ const filename = cachedNormalize(raw);
45
+ if (isInAny(filename, args.skipPackageDirs)) {
46
+ cachePut(cacheKey, null);
47
+ continue;
48
+ }
49
+ const rel = repoRelative(filename, args.repoRoot);
50
+ if (rel !== null && isBlocked(rel, args.blockList)) {
51
+ cachePut(cacheKey, null);
52
+ continue;
53
+ }
54
+ const resolvedFile = rel === null ? CALLER_FILE_EXTERNAL : rel;
55
+ const result = applyCap(resolvedFile, fnName, args.maxCallSites);
56
+ cachePut(cacheKey, result);
57
+ return result;
58
+ }
59
+ return { file: CALLER_FILE_UNKNOWN, function: "<unknown>" };
60
+ }
61
+ function applyCap(file, fn, maxCallSites) {
62
+ if (maxCallSites <= 0) {
63
+ return { file, function: fn };
64
+ }
65
+ const key = file + "\0" + fn;
66
+ if (seenCallSites.has(key)) {
67
+ return { file, function: fn };
68
+ }
69
+ if (seenCallSites.size < maxCallSites) {
70
+ seenCallSites.add(key);
71
+ seenFiles.add(file);
72
+ return { file, function: fn };
73
+ }
74
+ // At cap — soft overflow: keep file if we've seen it, else collapse both.
75
+ if (!capHitNotified) {
76
+ capHitNotified = true;
77
+ capHitPending = true;
78
+ }
79
+ if (seenFiles.has(file)) {
80
+ return { file, function: CALLER_OVERFLOW };
81
+ }
82
+ return { file: CALLER_OVERFLOW, function: CALLER_OVERFLOW };
83
+ }
84
+ /**
85
+ * Returns true iff a cardinality cap was crossed since the last call.
86
+ * Designed to be called once per `startCall` so the instrument layer can
87
+ * emit a single `frugal.gen_ai.internal_errors{stage=cardinality_cap_hit}`.
88
+ */
89
+ export function consumeCapHitEvent() {
90
+ if (capHitPending) {
91
+ capHitPending = false;
92
+ return true;
93
+ }
94
+ return false;
95
+ }
96
+ function captureCallSites(skipFrames) {
97
+ const originalPrepare = Error.prepareStackTrace;
98
+ const originalLimit = Error.stackTraceLimit;
99
+ try {
100
+ Error.stackTraceLimit = 20;
101
+ Error.prepareStackTrace = (_err, sites) => sites;
102
+ const holder = {};
103
+ Error.captureStackTrace(holder, captureCallSites);
104
+ const sites = holder.stack ?? [];
105
+ return sites.slice(skipFrames);
106
+ }
107
+ finally {
108
+ Error.prepareStackTrace = originalPrepare;
109
+ Error.stackTraceLimit = originalLimit;
110
+ }
111
+ }
112
+ function cachedNormalize(filename) {
113
+ const hit = realpathCache.get(filename);
114
+ if (hit !== undefined)
115
+ return hit;
116
+ const resolved = normalize(filename);
117
+ if (realpathCache.size < CACHE_MAX_SIZE) {
118
+ realpathCache.set(filename, resolved);
119
+ }
120
+ return resolved;
121
+ }
122
+ function normalize(filename) {
123
+ let f = filename;
124
+ if (f.startsWith("file://")) {
125
+ try {
126
+ f = fileURLToPath(f);
127
+ }
128
+ catch {
129
+ // leave as-is
130
+ }
131
+ }
132
+ try {
133
+ return realpathSync(f);
134
+ }
135
+ catch {
136
+ return f;
137
+ }
138
+ }
139
+ function cachePut(key, value) {
140
+ if (callerCache.size < CACHE_MAX_SIZE) {
141
+ callerCache.set(key, value);
142
+ }
143
+ }
144
+ function isInAny(filename, dirs) {
145
+ for (const d of dirs) {
146
+ if (!d)
147
+ continue;
148
+ const withSep = d.endsWith(sep) ? d : d + sep;
149
+ if (filename === d || filename.startsWith(withSep))
150
+ return true;
151
+ }
152
+ return false;
153
+ }
154
+ function repoRelative(filename, repoRoot) {
155
+ if (!filename)
156
+ return null;
157
+ const root = repoRoot.endsWith(sep) ? repoRoot.slice(0, -1) : repoRoot;
158
+ if (filename === root)
159
+ return "";
160
+ const prefix = root + sep;
161
+ if (filename.startsWith(prefix))
162
+ return filename.slice(prefix.length);
163
+ return null;
164
+ }
165
+ function isBlocked(relPath, blockList) {
166
+ for (const entry of blockList) {
167
+ if (!entry)
168
+ continue;
169
+ const trimmed = entry.replace(/\/+$/g, "");
170
+ if (relPath === trimmed || relPath.startsWith(trimmed + "/"))
171
+ return true;
172
+ }
173
+ return false;
174
+ }
175
+ export function packageDirFor(anyPathInPackage) {
176
+ let file = anyPathInPackage;
177
+ if (file.startsWith("file://")) {
178
+ try {
179
+ file = fileURLToPath(file);
180
+ }
181
+ catch {
182
+ // leave as-is
183
+ }
184
+ }
185
+ try {
186
+ const real = realpathSync(file);
187
+ const idx = real.lastIndexOf(sep);
188
+ return idx >= 0 ? real.slice(0, idx) : real;
189
+ }
190
+ catch {
191
+ const idx = file.lastIndexOf(sep);
192
+ return idx >= 0 ? file.slice(0, idx) : file;
193
+ }
194
+ }
195
+ /** Test-only hook — clear all caches. */
196
+ export function resetCachesForTests() {
197
+ realpathCache.clear();
198
+ callerCache.clear();
199
+ seenCallSites.clear();
200
+ seenFiles.clear();
201
+ capHitNotified = false;
202
+ capHitPending = false;
203
+ }
204
+ //# sourceMappingURL=caller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"caller.js","sourceRoot":"","sources":["../src/caller.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ export interface Config {
2
+ /** Optional now — when null the tenant label (auto-injected by VMAuth) identifies the customer. */
3
+ customerId: string | null;
4
+ /** Frugal project this deployment belongs to — the primary attribution key. */
5
+ projectId: string;
6
+ /** Optional logical components this deployment serves; metrics fan out one extra series per entry. */
7
+ components: readonly string[];
8
+ repoRoot: string;
9
+ pathBlockList: readonly string[];
10
+ otlpEndpoint: string;
11
+ otlpHeaders: string;
12
+ exportIntervalMs: number;
13
+ /** Max distinct (file, function) combinations to attribute before overflow. 0 = unlimited. */
14
+ maxCallSites: number;
15
+ /** Fraction of analyzed calls to emit prompt-analysis metrics for, 0..1. */
16
+ promptAnalysisSampleRate: number;
17
+ }
18
+ export declare function loadConfig(): Config | null;
19
+ /** Test-only hook to re-arm the one-shot warning. */
20
+ export declare function resetWarningStateForTests(): void;
21
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAgCA,MAAM,WAAW,MAAM;IACrB,mGAAmG;IACnG,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,+EAA+E;IAC/E,SAAS,EAAE,MAAM,CAAC;IAClB,sGAAsG;IACtG,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,8FAA8F;IAC9F,YAAY,EAAE,MAAM,CAAC;IACrB,4EAA4E;IAC5E,wBAAwB,EAAE,MAAM,CAAC;CAClC;AA2CD,wBAAgB,UAAU,IAAI,MAAM,GAAG,IAAI,CAmG1C;AAED,qDAAqD;AACrD,wBAAgB,yBAAyB,IAAI,IAAI,CAEhD"}
package/dist/config.js ADDED
@@ -0,0 +1,165 @@
1
+ // Environment-variable configuration loading.
2
+ //
3
+ // All configuration comes from env vars — no init() API. If any required
4
+ // variable is missing, loadConfig() returns null and the wrappers no-op. A
5
+ // single warning is logged on the first no-op.
6
+ //
7
+ // Minimum required production config (two env vars):
8
+ // FRUGAL_API_KEY — per-customer bearer token (Frugal mints these per tenant)
9
+ // FRUGAL_PROJECT_ID — the Frugal project this deployment belongs to. Stats are
10
+ // attributed per project (file/function is unique within a
11
+ // project), so the same repo deployed across microservices
12
+ // no longer collides. Frugal shows this value in the UI.
13
+ //
14
+ // Everything else has sensible defaults:
15
+ // - Endpoint defaults to https://metrics.frugal.co/opentelemetry/v1/metrics
16
+ // - REPO_ROOT defaults to process.cwd() (the strip prefix for caller_file)
17
+ // - CUSTOMER_ID is optional; when unset, the tenant label (auto-injected
18
+ // server-side by VMAuth from the bearer token) is the canonical customer
19
+ // identifier and the frugal.customer_id label is omitted.
20
+ // - COMPONENTS is optional; a comma-separated list (e.g. "ai-handler,reco").
21
+ // When set, every metric is ALSO emitted once per component (tagged with
22
+ // frugal.component) on top of the base project-level series, so usage can be
23
+ // viewed for the whole project (component absent) or split by component.
24
+ //
25
+ // The older env vars (FRUGAL_OTEL_EXPORTER_OTLP_ENDPOINT,
26
+ // FRUGAL_OTEL_EXPORTER_OTLP_HEADERS, FRUGAL_REPO_ROOT, FRUGAL_CUSTOMER_ID,
27
+ // plus the standard OTel ones) all still work — explicit values override
28
+ // the defaults so existing customers don't need to change anything.
29
+ import { realpathSync } from "node:fs";
30
+ import { resolve } from "node:path";
31
+ const ENV = {
32
+ CUSTOMER_ID: "FRUGAL_CUSTOMER_ID",
33
+ PROJECT_ID: "FRUGAL_PROJECT_ID",
34
+ // Namespaced overrides that take precedence over the bare FRUGAL_* names.
35
+ // Use these when embedding the SDK in an app that already owns FRUGAL_PROJECT_ID
36
+ // / FRUGAL_API_KEY for its own configuration (e.g. a Frugal-product service).
37
+ METRICS_PROJECT_ID: "FRUGAL_METRICS_PROJECT_ID",
38
+ METRICS_API_KEY: "FRUGAL_METRICS_API_KEY",
39
+ COMPONENTS: "FRUGAL_COMPONENTS",
40
+ REPO_ROOT: "FRUGAL_REPO_ROOT",
41
+ PATH_BLOCK_LIST: "FRUGAL_PATH_BLOCK_LIST",
42
+ DISABLED: "FRUGAL_DISABLED",
43
+ API_KEY: "FRUGAL_API_KEY",
44
+ FRUGAL_OTLP_ENDPOINT: "FRUGAL_OTEL_EXPORTER_OTLP_ENDPOINT",
45
+ FRUGAL_OTLP_HEADERS: "FRUGAL_OTEL_EXPORTER_OTLP_HEADERS",
46
+ OTLP_ENDPOINT: "OTEL_EXPORTER_OTLP_ENDPOINT",
47
+ OTLP_HEADERS: "OTEL_EXPORTER_OTLP_HEADERS",
48
+ EXPORT_INTERVAL_MS: "FRUGAL_METRIC_EXPORT_INTERVAL_MS",
49
+ MAX_CALL_SITES: "FRUGAL_MAX_CALL_SITES",
50
+ PROMPT_ANALYSIS_SAMPLE_RATE: "FRUGAL_PROMPT_ANALYSIS_SAMPLE_RATE",
51
+ };
52
+ const DEFAULT_OTLP_ENDPOINT = "https://metrics.frugal.co/opentelemetry/v1/metrics";
53
+ const DEFAULT_MAX_CALL_SITES = 500;
54
+ const DEFAULT_PROMPT_ANALYSIS_SAMPLE_RATE = 0.1;
55
+ let warnedOnce = false;
56
+ function truthy(value) {
57
+ if (!value)
58
+ return false;
59
+ const v = value.trim().toLowerCase();
60
+ return v === "1" || v === "true" || v === "yes" || v === "on";
61
+ }
62
+ function warnOnce(message) {
63
+ if (warnedOnce)
64
+ return;
65
+ warnedOnce = true;
66
+ // eslint-disable-next-line no-console
67
+ console.warn(`[frugal-metrics] disabled: ${message}`);
68
+ }
69
+ export function loadConfig() {
70
+ if (truthy(process.env[ENV.DISABLED]))
71
+ return null;
72
+ const customerId = process.env[ENV.CUSTOMER_ID] || null;
73
+ // Prefer the namespaced override so the SDK can coexist with a host app that
74
+ // uses FRUGAL_PROJECT_ID / FRUGAL_API_KEY for its own config. `||` so an empty
75
+ // override falls through to the bare name rather than blanking the value.
76
+ const projectId = process.env[ENV.METRICS_PROJECT_ID] || process.env[ENV.PROJECT_ID];
77
+ const repoRootEnv = process.env[ENV.REPO_ROOT];
78
+ const apiKey = process.env[ENV.METRICS_API_KEY] || process.env[ENV.API_KEY];
79
+ // Explicit headers override anything we'd build from the API key — keeps
80
+ // existing deployments that set FRUGAL_OTEL_EXPORTER_OTLP_HEADERS directly
81
+ // working unchanged.
82
+ const explicitHeaders = process.env[ENV.FRUGAL_OTLP_HEADERS] ?? process.env[ENV.OTLP_HEADERS];
83
+ const otlpHeaders = explicitHeaders
84
+ ? explicitHeaders
85
+ : apiKey
86
+ ? `Authorization=Bearer ${apiKey}`
87
+ : null;
88
+ // Required for any useful run: PROJECT_ID (the attribution key) and SOME auth
89
+ // (either FRUGAL_API_KEY or an explicit OTLP_HEADERS containing the bearer).
90
+ const missing = [];
91
+ if (!projectId)
92
+ missing.push(ENV.PROJECT_ID);
93
+ if (!otlpHeaders)
94
+ missing.push(`${ENV.API_KEY} or ${ENV.FRUGAL_OTLP_HEADERS}`);
95
+ if (missing.length > 0) {
96
+ warnOnce(`missing required env vars: ${missing.join(", ")}`);
97
+ return null;
98
+ }
99
+ // Resolve through symlinks so caller-file relativization is consistent with
100
+ // what Node reports in stack traces (esp. macOS /var -> /private/var).
101
+ // Default to process.cwd() — works for the standard container pattern
102
+ // where WORKDIR is set to the source-code root.
103
+ const repoRootRaw = repoRootEnv || process.cwd();
104
+ let repoRootAbs;
105
+ try {
106
+ repoRootAbs = realpathSync(resolve(repoRootRaw));
107
+ }
108
+ catch {
109
+ repoRootAbs = resolve(repoRootRaw);
110
+ }
111
+ const blockListRaw = process.env[ENV.PATH_BLOCK_LIST] ?? "";
112
+ const pathBlockList = blockListRaw
113
+ .split(",")
114
+ .map((e) => e.trim().replace(/^\/+|\/+$/g, ""))
115
+ .filter((e) => e.length > 0);
116
+ // Optional comma-separated logical components (e.g. "ai-handler,reco"). Each
117
+ // becomes an extra per-component series on top of the base project series.
118
+ const componentsRaw = process.env[ENV.COMPONENTS] ?? "";
119
+ const components = componentsRaw
120
+ .split(",")
121
+ .map((e) => e.trim())
122
+ .filter((e) => e.length > 0);
123
+ const otlpEndpoint = process.env[ENV.FRUGAL_OTLP_ENDPOINT] ??
124
+ process.env[ENV.OTLP_ENDPOINT] ??
125
+ DEFAULT_OTLP_ENDPOINT;
126
+ const intervalRaw = process.env[ENV.EXPORT_INTERVAL_MS];
127
+ let exportIntervalMs = 60_000;
128
+ if (intervalRaw && intervalRaw.trim()) {
129
+ const parsed = Number.parseInt(intervalRaw, 10);
130
+ if (Number.isFinite(parsed))
131
+ exportIntervalMs = parsed;
132
+ }
133
+ const maxCallSitesRaw = process.env[ENV.MAX_CALL_SITES];
134
+ let maxCallSites = DEFAULT_MAX_CALL_SITES;
135
+ if (maxCallSitesRaw && maxCallSitesRaw.trim()) {
136
+ const parsed = Number.parseInt(maxCallSitesRaw, 10);
137
+ if (Number.isFinite(parsed) && parsed >= 0)
138
+ maxCallSites = parsed;
139
+ }
140
+ const sampleRateRaw = process.env[ENV.PROMPT_ANALYSIS_SAMPLE_RATE];
141
+ let promptAnalysisSampleRate = DEFAULT_PROMPT_ANALYSIS_SAMPLE_RATE;
142
+ if (sampleRateRaw && sampleRateRaw.trim()) {
143
+ const parsed = Number.parseFloat(sampleRateRaw);
144
+ if (Number.isFinite(parsed) && parsed >= 0 && parsed <= 1) {
145
+ promptAnalysisSampleRate = parsed;
146
+ }
147
+ }
148
+ return {
149
+ customerId,
150
+ projectId: projectId,
151
+ components,
152
+ repoRoot: repoRootAbs,
153
+ pathBlockList,
154
+ otlpEndpoint,
155
+ otlpHeaders: otlpHeaders,
156
+ exportIntervalMs,
157
+ maxCallSites,
158
+ promptAnalysisSampleRate,
159
+ };
160
+ }
161
+ /** Test-only hook to re-arm the one-shot warning. */
162
+ export function resetWarningStateForTests() {
163
+ warnedOnce = false;
164
+ }
165
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export { wrapOpenAI } from "./wrappers/openai.js";
2
+ export { wrapAnthropic } from "./wrappers/anthropic.js";
3
+ export { wrapBedrock } from "./wrappers/bedrock.js";
4
+ export { startAICall, trackAICall } from "./track.js";
5
+ export type { AICallInfo, AIUsage, AICallHandle } from "./track.js";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACtD,YAAY,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export { wrapOpenAI } from "./wrappers/openai.js";
2
+ export { wrapAnthropic } from "./wrappers/anthropic.js";
3
+ export { wrapBedrock } from "./wrappers/bedrock.js";
4
+ export { startAICall, trackAICall } from "./track.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,49 @@
1
+ import { type CallerInfo } from "./caller.js";
2
+ import type { Config } from "./config.js";
3
+ import { type Instruments } from "./otel.js";
4
+ import { type RequestPayload } from "./prompt-analyzer.js";
5
+ export interface CallContext {
6
+ system: string;
7
+ operation: string;
8
+ requestModel: string;
9
+ skipPackageDirs: readonly string[];
10
+ /** True when this call is a batch-API submission, false for normal sync/streaming. */
11
+ batched?: boolean;
12
+ /** Captured request kwargs for prompt analysis + cap utilization. */
13
+ requestPayload?: RequestPayload;
14
+ }
15
+ export interface UsageReport {
16
+ responseModel?: string | null;
17
+ inputTokens?: number | null;
18
+ outputTokens?: number | null;
19
+ cacheReadTokens?: number | null;
20
+ cacheWriteTokens?: number | null;
21
+ reasoningTokens?: number | null;
22
+ }
23
+ export interface StartCallOptions {
24
+ /**
25
+ * How many frames at the top of the stack to skip past when resolving the
26
+ * caller. Default 2 drops resolveCaller + startCall, leaving the wrapper
27
+ * frame — resolveCaller then skips our wrapper frame via skipPackageDirs to
28
+ * land on the customer's code.
29
+ */
30
+ skipFrames?: number;
31
+ caller?: CallerInfo;
32
+ }
33
+ export declare function startCall(config: Config, ctx: CallContext, opts?: StartCallOptions): CallEmitter;
34
+ export declare class CallEmitter {
35
+ private readonly config;
36
+ private readonly ctx;
37
+ readonly caller: CallerInfo;
38
+ private readonly instruments;
39
+ private readonly startSec;
40
+ private finalized;
41
+ constructor(config: Config, ctx: CallContext, caller: CallerInfo, instruments: Instruments, startSec: number);
42
+ success(usage: UsageReport): void;
43
+ private recordCapUtilization;
44
+ private maybeAnalyze;
45
+ private recordStable;
46
+ error(err: unknown): void;
47
+ private baseAttrs;
48
+ }
49
+ //# sourceMappingURL=instrument.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instrument.d.ts","sourceRoot":"","sources":["../src/instrument.ts"],"names":[],"mappings":"AAUA,OAAO,EAGL,KAAK,UAAU,EAChB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AAE7D,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,sBAAsB,CAAC;AAwB9B,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,sFAAsF;IACtF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,qEAAqE;IACrE,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC;AAED,MAAM,WAAW,WAAW;IAC1B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AAED,MAAM,WAAW,gBAAgB;IAC/B;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED,wBAAgB,SAAS,CACvB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,WAAW,EAChB,IAAI,GAAE,gBAAqB,GAC1B,WAAW,CAuBb;AAOD,qBAAa,WAAW;IAIpB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,QAAQ,CAAC,MAAM,EAAE,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAP3B,OAAO,CAAC,SAAS,CAAS;gBAGP,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,WAAW,EACxB,MAAM,EAAE,UAAU,EACV,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,MAAM;IAGnC,OAAO,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;IAqCjC,OAAO,CAAC,oBAAoB;IAa5B,OAAO,CAAC,YAAY;IAyCpB,OAAO,CAAC,YAAY;IAgBpB,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI;IAWzB,OAAO,CAAC,SAAS;CAelB"}