@kayba_ai/tracing 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.
@@ -0,0 +1,85 @@
1
+ import * as mlflow_tracing from 'mlflow-tracing';
2
+ import { SpanType } from 'mlflow-tracing';
3
+ export { LiveSpan, Span, SpanType } from 'mlflow-tracing';
4
+
5
+ interface ConfigureOptions {
6
+ /** Kayba API key. Falls back to `KAYBA_API_KEY` env var. */
7
+ apiKey?: string;
8
+ /** Kayba API base URL. Falls back to `KAYBA_API_URL` env var, then `https://use.kayba.ai`. */
9
+ baseUrl?: string;
10
+ /** Alias for `folder`. If both provided, `folder` takes precedence. */
11
+ experiment?: string;
12
+ /** Folder name for organizing traces in the Kayba dashboard. */
13
+ folder?: string;
14
+ /** MLflow experiment ID. Defaults to `"0"`. */
15
+ experimentId?: string;
16
+ }
17
+ interface TraceOptions {
18
+ /** Custom span name. Defaults to the function name. */
19
+ name?: string;
20
+ /** Span type (e.g. SpanType.LLM, SpanType.AGENT). */
21
+ spanType?: SpanType;
22
+ /** Additional span attributes. */
23
+ attributes?: Record<string, unknown>;
24
+ }
25
+ interface StartSpanOptions {
26
+ /** Span name. */
27
+ name: string;
28
+ /** Span type. */
29
+ spanType?: SpanType;
30
+ /** Input data to attach to the span. */
31
+ inputs?: Record<string, unknown>;
32
+ }
33
+ /**
34
+ * Configure Kayba tracing.
35
+ *
36
+ * Sets the MLflow tracking URI and authentication so that all
37
+ * subsequent `trace` / `startSpan` calls export to Kayba.
38
+ */
39
+ declare function configure(options?: ConfigureOptions): void;
40
+ /**
41
+ * Change the target folder for subsequent traces.
42
+ *
43
+ * @param folder - Folder name, or `null` to clear (traces go to Unfiled).
44
+ */
45
+ declare function setFolder(folder: string | null): void;
46
+ /** Return the currently configured folder, or `null`. */
47
+ declare function getFolder(): string | null;
48
+ /**
49
+ * Wrap a function with tracing. The returned function generates a span
50
+ * each time it is called, with automatic folder tagging.
51
+ *
52
+ * @example
53
+ * ```ts
54
+ * const myFunc = trace(async (input: string) => {
55
+ * return doWork(input);
56
+ * }, { name: "my_func", spanType: SpanType.LLM });
57
+ * ```
58
+ */
59
+ declare function trace<T extends (...args: any[]) => any>(fn: T, options?: TraceOptions): T;
60
+ /**
61
+ * Create a span manually. Call `.end()` when done.
62
+ *
63
+ * @example
64
+ * ```ts
65
+ * const span = startSpan({ name: "retrieval", spanType: SpanType.TOOL });
66
+ * span.setInputs({ query });
67
+ * // ... work ...
68
+ * span.end({ outputs: { result }, status: "OK" });
69
+ * ```
70
+ */
71
+ declare function startSpan(options: StartSpanOptions): mlflow_tracing.LiveSpan;
72
+ /** Returns whether `configure()` has been called. */
73
+ declare function isConfigured(): boolean;
74
+
75
+ declare const kayba: {
76
+ configure: typeof configure;
77
+ trace: typeof trace;
78
+ startSpan: typeof startSpan;
79
+ setFolder: typeof setFolder;
80
+ getFolder: typeof getFolder;
81
+ isConfigured: typeof isConfigured;
82
+ SpanType: typeof SpanType;
83
+ };
84
+
85
+ export { type ConfigureOptions, type StartSpanOptions, type TraceOptions, configure, kayba as default, getFolder, isConfigured, setFolder, startSpan, trace };
@@ -0,0 +1,85 @@
1
+ import * as mlflow_tracing from 'mlflow-tracing';
2
+ import { SpanType } from 'mlflow-tracing';
3
+ export { LiveSpan, Span, SpanType } from 'mlflow-tracing';
4
+
5
+ interface ConfigureOptions {
6
+ /** Kayba API key. Falls back to `KAYBA_API_KEY` env var. */
7
+ apiKey?: string;
8
+ /** Kayba API base URL. Falls back to `KAYBA_API_URL` env var, then `https://use.kayba.ai`. */
9
+ baseUrl?: string;
10
+ /** Alias for `folder`. If both provided, `folder` takes precedence. */
11
+ experiment?: string;
12
+ /** Folder name for organizing traces in the Kayba dashboard. */
13
+ folder?: string;
14
+ /** MLflow experiment ID. Defaults to `"0"`. */
15
+ experimentId?: string;
16
+ }
17
+ interface TraceOptions {
18
+ /** Custom span name. Defaults to the function name. */
19
+ name?: string;
20
+ /** Span type (e.g. SpanType.LLM, SpanType.AGENT). */
21
+ spanType?: SpanType;
22
+ /** Additional span attributes. */
23
+ attributes?: Record<string, unknown>;
24
+ }
25
+ interface StartSpanOptions {
26
+ /** Span name. */
27
+ name: string;
28
+ /** Span type. */
29
+ spanType?: SpanType;
30
+ /** Input data to attach to the span. */
31
+ inputs?: Record<string, unknown>;
32
+ }
33
+ /**
34
+ * Configure Kayba tracing.
35
+ *
36
+ * Sets the MLflow tracking URI and authentication so that all
37
+ * subsequent `trace` / `startSpan` calls export to Kayba.
38
+ */
39
+ declare function configure(options?: ConfigureOptions): void;
40
+ /**
41
+ * Change the target folder for subsequent traces.
42
+ *
43
+ * @param folder - Folder name, or `null` to clear (traces go to Unfiled).
44
+ */
45
+ declare function setFolder(folder: string | null): void;
46
+ /** Return the currently configured folder, or `null`. */
47
+ declare function getFolder(): string | null;
48
+ /**
49
+ * Wrap a function with tracing. The returned function generates a span
50
+ * each time it is called, with automatic folder tagging.
51
+ *
52
+ * @example
53
+ * ```ts
54
+ * const myFunc = trace(async (input: string) => {
55
+ * return doWork(input);
56
+ * }, { name: "my_func", spanType: SpanType.LLM });
57
+ * ```
58
+ */
59
+ declare function trace<T extends (...args: any[]) => any>(fn: T, options?: TraceOptions): T;
60
+ /**
61
+ * Create a span manually. Call `.end()` when done.
62
+ *
63
+ * @example
64
+ * ```ts
65
+ * const span = startSpan({ name: "retrieval", spanType: SpanType.TOOL });
66
+ * span.setInputs({ query });
67
+ * // ... work ...
68
+ * span.end({ outputs: { result }, status: "OK" });
69
+ * ```
70
+ */
71
+ declare function startSpan(options: StartSpanOptions): mlflow_tracing.LiveSpan;
72
+ /** Returns whether `configure()` has been called. */
73
+ declare function isConfigured(): boolean;
74
+
75
+ declare const kayba: {
76
+ configure: typeof configure;
77
+ trace: typeof trace;
78
+ startSpan: typeof startSpan;
79
+ setFolder: typeof setFolder;
80
+ getFolder: typeof getFolder;
81
+ isConfigured: typeof isConfigured;
82
+ SpanType: typeof SpanType;
83
+ };
84
+
85
+ export { type ConfigureOptions, type StartSpanOptions, type TraceOptions, configure, kayba as default, getFolder, isConfigured, setFolder, startSpan, trace };
package/dist/index.js ADDED
@@ -0,0 +1,143 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ SpanType: () => import_mlflow_tracing2.SpanType,
24
+ configure: () => configure,
25
+ default: () => index_default,
26
+ getFolder: () => getFolder,
27
+ isConfigured: () => isConfigured,
28
+ setFolder: () => setFolder,
29
+ startSpan: () => startSpan,
30
+ trace: () => trace
31
+ });
32
+ module.exports = __toCommonJS(index_exports);
33
+ var import_mlflow_tracing = require("mlflow-tracing");
34
+ var import_mlflow_tracing2 = require("mlflow-tracing");
35
+ var DEFAULT_BASE_URL = "https://use.kayba.ai";
36
+ var MAX_FOLDER_LENGTH = 256;
37
+ var SAFE_FOLDER_RE = /[^a-zA-Z0-9 _\-/.]/g;
38
+ var HTML_TAG_RE = /<[^>]*>/g;
39
+ var _folder = null;
40
+ var _configured = false;
41
+ function sanitizeFolder(name) {
42
+ let clean = name.replace(HTML_TAG_RE, "");
43
+ clean = clean.replace(SAFE_FOLDER_RE, "");
44
+ return clean.trim().slice(0, MAX_FOLDER_LENGTH);
45
+ }
46
+ function resolveFolder(folder, experiment) {
47
+ const raw = folder ?? experiment;
48
+ if (!raw) return null;
49
+ const sanitized = sanitizeFolder(raw);
50
+ return sanitized || null;
51
+ }
52
+ function injectFolderTag() {
53
+ if (_folder !== null) {
54
+ try {
55
+ (0, import_mlflow_tracing.updateCurrentTrace)({ tags: { "kayba.folder": _folder } });
56
+ } catch {
57
+ }
58
+ }
59
+ }
60
+ function configure(options = {}) {
61
+ const apiKey = options.apiKey || process.env.KAYBA_API_KEY || "";
62
+ if (!apiKey) {
63
+ throw new Error(
64
+ "No API key provided. Pass apiKey or set the KAYBA_API_KEY environment variable."
65
+ );
66
+ }
67
+ const baseUrl = options.baseUrl || process.env.KAYBA_API_URL || DEFAULT_BASE_URL;
68
+ const trackingUri = baseUrl.replace(/\/+$/, "") + "/api/mlflow";
69
+ process.env.MLFLOW_TRACKING_TOKEN = apiKey;
70
+ process.env.MLFLOW_TRACKING_URI = trackingUri;
71
+ const experimentId = options.experimentId || process.env.MLFLOW_EXPERIMENT_ID || "0";
72
+ (0, import_mlflow_tracing.init)({ trackingUri, experimentId });
73
+ _folder = resolveFolder(options.folder, options.experiment);
74
+ _configured = true;
75
+ }
76
+ function setFolder(folder) {
77
+ if (folder === null) {
78
+ _folder = null;
79
+ } else {
80
+ const sanitized = sanitizeFolder(folder);
81
+ _folder = sanitized || null;
82
+ }
83
+ }
84
+ function getFolder() {
85
+ return _folder;
86
+ }
87
+ function trace(fn, options = {}) {
88
+ const fnWithTag = (...args) => {
89
+ const result = fn(...args);
90
+ if (result instanceof Promise) {
91
+ return result.then((value) => {
92
+ injectFolderTag();
93
+ return value;
94
+ });
95
+ }
96
+ injectFolderTag();
97
+ return result;
98
+ };
99
+ const mlflowOptions = {};
100
+ if (options.name) mlflowOptions.name = options.name;
101
+ if (options.spanType) mlflowOptions.spanType = options.spanType;
102
+ if (options.attributes)
103
+ mlflowOptions.attributes = options.attributes;
104
+ return (0, import_mlflow_tracing.trace)(fnWithTag, mlflowOptions);
105
+ }
106
+ function startSpan(options) {
107
+ const mlflowOptions = {
108
+ name: options.name
109
+ };
110
+ if (options.spanType) mlflowOptions.spanType = options.spanType;
111
+ if (options.inputs) mlflowOptions.inputs = options.inputs;
112
+ const span = (0, import_mlflow_tracing.startSpan)(mlflowOptions);
113
+ const originalEnd = span.end.bind(span);
114
+ span.end = (endOptions) => {
115
+ injectFolderTag();
116
+ return originalEnd(endOptions);
117
+ };
118
+ return span;
119
+ }
120
+ function isConfigured() {
121
+ return _configured;
122
+ }
123
+ var kayba = {
124
+ configure,
125
+ trace,
126
+ startSpan,
127
+ setFolder,
128
+ getFolder,
129
+ isConfigured,
130
+ SpanType: import_mlflow_tracing.SpanType
131
+ };
132
+ var index_default = kayba;
133
+ // Annotate the CommonJS export names for ESM import in node:
134
+ 0 && (module.exports = {
135
+ SpanType,
136
+ configure,
137
+ getFolder,
138
+ isConfigured,
139
+ setFolder,
140
+ startSpan,
141
+ trace
142
+ });
143
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Kayba tracing SDK for TypeScript/Node.js.\n *\n * Thin wrapper around `mlflow-tracing` that configures auth and\n * injects Kayba-specific folder tags.\n *\n * @example\n * ```ts\n * import kayba from \"@kayba_ai/tracing\";\n *\n * kayba.configure({\n * apiKey: process.env.KAYBA_API_KEY,\n * folder: \"my-project\",\n * });\n *\n * const myAgent = kayba.trace(async (topic: string) => {\n * const span = kayba.startSpan({ name: \"retrieval\" });\n * // ... work ...\n * span.end({ status: \"OK\" });\n * return result;\n * }, { name: \"research_agent\" });\n * ```\n */\n\nimport {\n init,\n trace as mlflowTrace,\n startSpan as mlflowStartSpan,\n updateCurrentTrace,\n SpanType,\n type TraceOptions as MlflowTraceOptions,\n type SpanOptions as MlflowSpanOptions,\n} from \"mlflow-tracing\";\n\n// ── Constants ──────────────────────────────────────────────────────────\n\nconst DEFAULT_BASE_URL = \"https://use.kayba.ai\";\nconst MAX_FOLDER_LENGTH = 256;\nconst SAFE_FOLDER_RE = /[^a-zA-Z0-9 _\\-/.]/g;\nconst HTML_TAG_RE = /<[^>]*>/g;\n\n// ── Module state ───────────────────────────────────────────────────────\n\nlet _folder: string | null = null;\nlet _configured = false;\n\n// ── Types ──────────────────────────────────────────────────────────────\n\nexport interface ConfigureOptions {\n /** Kayba API key. Falls back to `KAYBA_API_KEY` env var. */\n apiKey?: string;\n /** Kayba API base URL. Falls back to `KAYBA_API_URL` env var, then `https://use.kayba.ai`. */\n baseUrl?: string;\n /** Alias for `folder`. If both provided, `folder` takes precedence. */\n experiment?: string;\n /** Folder name for organizing traces in the Kayba dashboard. */\n folder?: string;\n /** MLflow experiment ID. Defaults to `\"0\"`. */\n experimentId?: string;\n}\n\nexport interface TraceOptions {\n /** Custom span name. Defaults to the function name. */\n name?: string;\n /** Span type (e.g. SpanType.LLM, SpanType.AGENT). */\n spanType?: SpanType;\n /** Additional span attributes. */\n attributes?: Record<string, unknown>;\n}\n\nexport interface StartSpanOptions {\n /** Span name. */\n name: string;\n /** Span type. */\n spanType?: SpanType;\n /** Input data to attach to the span. */\n inputs?: Record<string, unknown>;\n}\n\n// ── Internal helpers ───────────────────────────────────────────────────\n\nfunction sanitizeFolder(name: string): string {\n let clean = name.replace(HTML_TAG_RE, \"\");\n clean = clean.replace(SAFE_FOLDER_RE, \"\");\n return clean.trim().slice(0, MAX_FOLDER_LENGTH);\n}\n\nfunction resolveFolder(\n folder: string | undefined,\n experiment: string | undefined,\n): string | null {\n const raw = folder ?? experiment;\n if (!raw) return null;\n const sanitized = sanitizeFolder(raw);\n return sanitized || null;\n}\n\nfunction injectFolderTag(): void {\n if (_folder !== null) {\n try {\n updateCurrentTrace({ tags: { \"kayba.folder\": _folder } });\n } catch {\n // Silently ignore if no active trace context.\n }\n }\n}\n\n// ── Public API ─────────────────────────────────────────────────────────\n\n/**\n * Configure Kayba tracing.\n *\n * Sets the MLflow tracking URI and authentication so that all\n * subsequent `trace` / `startSpan` calls export to Kayba.\n */\nexport function configure(options: ConfigureOptions = {}): void {\n const apiKey = options.apiKey || process.env.KAYBA_API_KEY || \"\";\n\n if (!apiKey) {\n throw new Error(\n \"No API key provided. Pass apiKey or set the KAYBA_API_KEY environment variable.\",\n );\n }\n\n const baseUrl =\n options.baseUrl || process.env.KAYBA_API_URL || DEFAULT_BASE_URL;\n\n const trackingUri = baseUrl.replace(/\\/+$/, \"\") + \"/api/mlflow\";\n\n // Configure MLflow under the hood.\n process.env.MLFLOW_TRACKING_TOKEN = apiKey;\n process.env.MLFLOW_TRACKING_URI = trackingUri;\n\n const experimentId =\n options.experimentId || process.env.MLFLOW_EXPERIMENT_ID || \"0\";\n\n init({ trackingUri, experimentId });\n\n _folder = resolveFolder(options.folder, options.experiment);\n _configured = true;\n}\n\n/**\n * Change the target folder for subsequent traces.\n *\n * @param folder - Folder name, or `null` to clear (traces go to Unfiled).\n */\nexport function setFolder(folder: string | null): void {\n if (folder === null) {\n _folder = null;\n } else {\n const sanitized = sanitizeFolder(folder);\n _folder = sanitized || null;\n }\n}\n\n/** Return the currently configured folder, or `null`. */\nexport function getFolder(): string | null {\n return _folder;\n}\n\n/**\n * Wrap a function with tracing. The returned function generates a span\n * each time it is called, with automatic folder tagging.\n *\n * @example\n * ```ts\n * const myFunc = trace(async (input: string) => {\n * return doWork(input);\n * }, { name: \"my_func\", spanType: SpanType.LLM });\n * ```\n */\nexport function trace<T extends (...args: any[]) => any>(\n fn: T,\n options: TraceOptions = {},\n): T {\n // Wrap the function to inject the folder tag after execution.\n const fnWithTag = (...args: Parameters<T>): ReturnType<T> => {\n const result = fn(...args);\n\n // Handle async functions: inject tag after the promise resolves.\n if (result instanceof Promise) {\n return result.then((value: unknown) => {\n injectFolderTag();\n return value;\n }) as ReturnType<T>;\n }\n\n injectFolderTag();\n return result;\n };\n\n const mlflowOptions: MlflowTraceOptions = {};\n if (options.name) mlflowOptions.name = options.name;\n if (options.spanType) mlflowOptions.spanType = options.spanType;\n if (options.attributes)\n mlflowOptions.attributes = options.attributes as Record<string, any>;\n\n return mlflowTrace(fnWithTag as T, mlflowOptions);\n}\n\n/**\n * Create a span manually. Call `.end()` when done.\n *\n * @example\n * ```ts\n * const span = startSpan({ name: \"retrieval\", spanType: SpanType.TOOL });\n * span.setInputs({ query });\n * // ... work ...\n * span.end({ outputs: { result }, status: \"OK\" });\n * ```\n */\nexport function startSpan(options: StartSpanOptions) {\n const mlflowOptions: MlflowSpanOptions = {\n name: options.name,\n };\n if (options.spanType) mlflowOptions.spanType = options.spanType;\n if (options.inputs) mlflowOptions.inputs = options.inputs;\n\n const span = mlflowStartSpan(mlflowOptions);\n\n // Wrap .end() to inject the folder tag before closing.\n const originalEnd = span.end.bind(span);\n span.end = (endOptions?: Parameters<typeof span.end>[0]) => {\n injectFolderTag();\n return originalEnd(endOptions);\n };\n\n return span;\n}\n\n/** Returns whether `configure()` has been called. */\nexport function isConfigured(): boolean {\n return _configured;\n}\n\n// ── Re-export MLflow types for convenience ─────────────────────────────\n\nexport { SpanType } from \"mlflow-tracing\";\nexport type { LiveSpan, Span } from \"mlflow-tracing\";\n\n// ── Default export ─────────────────────────────────────────────────────\n\nconst kayba = {\n configure,\n trace,\n startSpan,\n setFolder,\n getFolder,\n isConfigured,\n SpanType,\n};\n\nexport default kayba;\n"],"mappings":"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","names":["import_mlflow_tracing","mlflowTrace","mlflowStartSpan"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,118 @@
1
+ // src/index.ts
2
+ import {
3
+ init,
4
+ trace as mlflowTrace,
5
+ startSpan as mlflowStartSpan,
6
+ updateCurrentTrace,
7
+ SpanType
8
+ } from "mlflow-tracing";
9
+ import { SpanType as SpanType2 } from "mlflow-tracing";
10
+ var DEFAULT_BASE_URL = "https://use.kayba.ai";
11
+ var MAX_FOLDER_LENGTH = 256;
12
+ var SAFE_FOLDER_RE = /[^a-zA-Z0-9 _\-/.]/g;
13
+ var HTML_TAG_RE = /<[^>]*>/g;
14
+ var _folder = null;
15
+ var _configured = false;
16
+ function sanitizeFolder(name) {
17
+ let clean = name.replace(HTML_TAG_RE, "");
18
+ clean = clean.replace(SAFE_FOLDER_RE, "");
19
+ return clean.trim().slice(0, MAX_FOLDER_LENGTH);
20
+ }
21
+ function resolveFolder(folder, experiment) {
22
+ const raw = folder ?? experiment;
23
+ if (!raw) return null;
24
+ const sanitized = sanitizeFolder(raw);
25
+ return sanitized || null;
26
+ }
27
+ function injectFolderTag() {
28
+ if (_folder !== null) {
29
+ try {
30
+ updateCurrentTrace({ tags: { "kayba.folder": _folder } });
31
+ } catch {
32
+ }
33
+ }
34
+ }
35
+ function configure(options = {}) {
36
+ const apiKey = options.apiKey || process.env.KAYBA_API_KEY || "";
37
+ if (!apiKey) {
38
+ throw new Error(
39
+ "No API key provided. Pass apiKey or set the KAYBA_API_KEY environment variable."
40
+ );
41
+ }
42
+ const baseUrl = options.baseUrl || process.env.KAYBA_API_URL || DEFAULT_BASE_URL;
43
+ const trackingUri = baseUrl.replace(/\/+$/, "") + "/api/mlflow";
44
+ process.env.MLFLOW_TRACKING_TOKEN = apiKey;
45
+ process.env.MLFLOW_TRACKING_URI = trackingUri;
46
+ const experimentId = options.experimentId || process.env.MLFLOW_EXPERIMENT_ID || "0";
47
+ init({ trackingUri, experimentId });
48
+ _folder = resolveFolder(options.folder, options.experiment);
49
+ _configured = true;
50
+ }
51
+ function setFolder(folder) {
52
+ if (folder === null) {
53
+ _folder = null;
54
+ } else {
55
+ const sanitized = sanitizeFolder(folder);
56
+ _folder = sanitized || null;
57
+ }
58
+ }
59
+ function getFolder() {
60
+ return _folder;
61
+ }
62
+ function trace(fn, options = {}) {
63
+ const fnWithTag = (...args) => {
64
+ const result = fn(...args);
65
+ if (result instanceof Promise) {
66
+ return result.then((value) => {
67
+ injectFolderTag();
68
+ return value;
69
+ });
70
+ }
71
+ injectFolderTag();
72
+ return result;
73
+ };
74
+ const mlflowOptions = {};
75
+ if (options.name) mlflowOptions.name = options.name;
76
+ if (options.spanType) mlflowOptions.spanType = options.spanType;
77
+ if (options.attributes)
78
+ mlflowOptions.attributes = options.attributes;
79
+ return mlflowTrace(fnWithTag, mlflowOptions);
80
+ }
81
+ function startSpan(options) {
82
+ const mlflowOptions = {
83
+ name: options.name
84
+ };
85
+ if (options.spanType) mlflowOptions.spanType = options.spanType;
86
+ if (options.inputs) mlflowOptions.inputs = options.inputs;
87
+ const span = mlflowStartSpan(mlflowOptions);
88
+ const originalEnd = span.end.bind(span);
89
+ span.end = (endOptions) => {
90
+ injectFolderTag();
91
+ return originalEnd(endOptions);
92
+ };
93
+ return span;
94
+ }
95
+ function isConfigured() {
96
+ return _configured;
97
+ }
98
+ var kayba = {
99
+ configure,
100
+ trace,
101
+ startSpan,
102
+ setFolder,
103
+ getFolder,
104
+ isConfigured,
105
+ SpanType
106
+ };
107
+ var index_default = kayba;
108
+ export {
109
+ SpanType2 as SpanType,
110
+ configure,
111
+ index_default as default,
112
+ getFolder,
113
+ isConfigured,
114
+ setFolder,
115
+ startSpan,
116
+ trace
117
+ };
118
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Kayba tracing SDK for TypeScript/Node.js.\n *\n * Thin wrapper around `mlflow-tracing` that configures auth and\n * injects Kayba-specific folder tags.\n *\n * @example\n * ```ts\n * import kayba from \"@kayba_ai/tracing\";\n *\n * kayba.configure({\n * apiKey: process.env.KAYBA_API_KEY,\n * folder: \"my-project\",\n * });\n *\n * const myAgent = kayba.trace(async (topic: string) => {\n * const span = kayba.startSpan({ name: \"retrieval\" });\n * // ... work ...\n * span.end({ status: \"OK\" });\n * return result;\n * }, { name: \"research_agent\" });\n * ```\n */\n\nimport {\n init,\n trace as mlflowTrace,\n startSpan as mlflowStartSpan,\n updateCurrentTrace,\n SpanType,\n type TraceOptions as MlflowTraceOptions,\n type SpanOptions as MlflowSpanOptions,\n} from \"mlflow-tracing\";\n\n// ── Constants ──────────────────────────────────────────────────────────\n\nconst DEFAULT_BASE_URL = \"https://use.kayba.ai\";\nconst MAX_FOLDER_LENGTH = 256;\nconst SAFE_FOLDER_RE = /[^a-zA-Z0-9 _\\-/.]/g;\nconst HTML_TAG_RE = /<[^>]*>/g;\n\n// ── Module state ───────────────────────────────────────────────────────\n\nlet _folder: string | null = null;\nlet _configured = false;\n\n// ── Types ──────────────────────────────────────────────────────────────\n\nexport interface ConfigureOptions {\n /** Kayba API key. Falls back to `KAYBA_API_KEY` env var. */\n apiKey?: string;\n /** Kayba API base URL. Falls back to `KAYBA_API_URL` env var, then `https://use.kayba.ai`. */\n baseUrl?: string;\n /** Alias for `folder`. If both provided, `folder` takes precedence. */\n experiment?: string;\n /** Folder name for organizing traces in the Kayba dashboard. */\n folder?: string;\n /** MLflow experiment ID. Defaults to `\"0\"`. */\n experimentId?: string;\n}\n\nexport interface TraceOptions {\n /** Custom span name. Defaults to the function name. */\n name?: string;\n /** Span type (e.g. SpanType.LLM, SpanType.AGENT). */\n spanType?: SpanType;\n /** Additional span attributes. */\n attributes?: Record<string, unknown>;\n}\n\nexport interface StartSpanOptions {\n /** Span name. */\n name: string;\n /** Span type. */\n spanType?: SpanType;\n /** Input data to attach to the span. */\n inputs?: Record<string, unknown>;\n}\n\n// ── Internal helpers ───────────────────────────────────────────────────\n\nfunction sanitizeFolder(name: string): string {\n let clean = name.replace(HTML_TAG_RE, \"\");\n clean = clean.replace(SAFE_FOLDER_RE, \"\");\n return clean.trim().slice(0, MAX_FOLDER_LENGTH);\n}\n\nfunction resolveFolder(\n folder: string | undefined,\n experiment: string | undefined,\n): string | null {\n const raw = folder ?? experiment;\n if (!raw) return null;\n const sanitized = sanitizeFolder(raw);\n return sanitized || null;\n}\n\nfunction injectFolderTag(): void {\n if (_folder !== null) {\n try {\n updateCurrentTrace({ tags: { \"kayba.folder\": _folder } });\n } catch {\n // Silently ignore if no active trace context.\n }\n }\n}\n\n// ── Public API ─────────────────────────────────────────────────────────\n\n/**\n * Configure Kayba tracing.\n *\n * Sets the MLflow tracking URI and authentication so that all\n * subsequent `trace` / `startSpan` calls export to Kayba.\n */\nexport function configure(options: ConfigureOptions = {}): void {\n const apiKey = options.apiKey || process.env.KAYBA_API_KEY || \"\";\n\n if (!apiKey) {\n throw new Error(\n \"No API key provided. Pass apiKey or set the KAYBA_API_KEY environment variable.\",\n );\n }\n\n const baseUrl =\n options.baseUrl || process.env.KAYBA_API_URL || DEFAULT_BASE_URL;\n\n const trackingUri = baseUrl.replace(/\\/+$/, \"\") + \"/api/mlflow\";\n\n // Configure MLflow under the hood.\n process.env.MLFLOW_TRACKING_TOKEN = apiKey;\n process.env.MLFLOW_TRACKING_URI = trackingUri;\n\n const experimentId =\n options.experimentId || process.env.MLFLOW_EXPERIMENT_ID || \"0\";\n\n init({ trackingUri, experimentId });\n\n _folder = resolveFolder(options.folder, options.experiment);\n _configured = true;\n}\n\n/**\n * Change the target folder for subsequent traces.\n *\n * @param folder - Folder name, or `null` to clear (traces go to Unfiled).\n */\nexport function setFolder(folder: string | null): void {\n if (folder === null) {\n _folder = null;\n } else {\n const sanitized = sanitizeFolder(folder);\n _folder = sanitized || null;\n }\n}\n\n/** Return the currently configured folder, or `null`. */\nexport function getFolder(): string | null {\n return _folder;\n}\n\n/**\n * Wrap a function with tracing. The returned function generates a span\n * each time it is called, with automatic folder tagging.\n *\n * @example\n * ```ts\n * const myFunc = trace(async (input: string) => {\n * return doWork(input);\n * }, { name: \"my_func\", spanType: SpanType.LLM });\n * ```\n */\nexport function trace<T extends (...args: any[]) => any>(\n fn: T,\n options: TraceOptions = {},\n): T {\n // Wrap the function to inject the folder tag after execution.\n const fnWithTag = (...args: Parameters<T>): ReturnType<T> => {\n const result = fn(...args);\n\n // Handle async functions: inject tag after the promise resolves.\n if (result instanceof Promise) {\n return result.then((value: unknown) => {\n injectFolderTag();\n return value;\n }) as ReturnType<T>;\n }\n\n injectFolderTag();\n return result;\n };\n\n const mlflowOptions: MlflowTraceOptions = {};\n if (options.name) mlflowOptions.name = options.name;\n if (options.spanType) mlflowOptions.spanType = options.spanType;\n if (options.attributes)\n mlflowOptions.attributes = options.attributes as Record<string, any>;\n\n return mlflowTrace(fnWithTag as T, mlflowOptions);\n}\n\n/**\n * Create a span manually. Call `.end()` when done.\n *\n * @example\n * ```ts\n * const span = startSpan({ name: \"retrieval\", spanType: SpanType.TOOL });\n * span.setInputs({ query });\n * // ... work ...\n * span.end({ outputs: { result }, status: \"OK\" });\n * ```\n */\nexport function startSpan(options: StartSpanOptions) {\n const mlflowOptions: MlflowSpanOptions = {\n name: options.name,\n };\n if (options.spanType) mlflowOptions.spanType = options.spanType;\n if (options.inputs) mlflowOptions.inputs = options.inputs;\n\n const span = mlflowStartSpan(mlflowOptions);\n\n // Wrap .end() to inject the folder tag before closing.\n const originalEnd = span.end.bind(span);\n span.end = (endOptions?: Parameters<typeof span.end>[0]) => {\n injectFolderTag();\n return originalEnd(endOptions);\n };\n\n return span;\n}\n\n/** Returns whether `configure()` has been called. */\nexport function isConfigured(): boolean {\n return _configured;\n}\n\n// ── Re-export MLflow types for convenience ─────────────────────────────\n\nexport { SpanType } from \"mlflow-tracing\";\nexport type { LiveSpan, Span } from \"mlflow-tracing\";\n\n// ── Default export ─────────────────────────────────────────────────────\n\nconst kayba = {\n configure,\n trace,\n startSpan,\n setFolder,\n getFolder,\n isConfigured,\n SpanType,\n};\n\nexport default kayba;\n"],"mappings":";AAwBA;AAAA,EACE;AAAA,EACA,SAAS;AAAA,EACT,aAAa;AAAA,EACb;AAAA,EACA;AAAA,OAGK;AA8MP,SAAS,YAAAA,iBAAgB;AA1MzB,IAAM,mBAAmB;AACzB,IAAM,oBAAoB;AAC1B,IAAM,iBAAiB;AACvB,IAAM,cAAc;AAIpB,IAAI,UAAyB;AAC7B,IAAI,cAAc;AAqClB,SAAS,eAAe,MAAsB;AAC5C,MAAI,QAAQ,KAAK,QAAQ,aAAa,EAAE;AACxC,UAAQ,MAAM,QAAQ,gBAAgB,EAAE;AACxC,SAAO,MAAM,KAAK,EAAE,MAAM,GAAG,iBAAiB;AAChD;AAEA,SAAS,cACP,QACA,YACe;AACf,QAAM,MAAM,UAAU;AACtB,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,YAAY,eAAe,GAAG;AACpC,SAAO,aAAa;AACtB;AAEA,SAAS,kBAAwB;AAC/B,MAAI,YAAY,MAAM;AACpB,QAAI;AACF,yBAAmB,EAAE,MAAM,EAAE,gBAAgB,QAAQ,EAAE,CAAC;AAAA,IAC1D,QAAQ;AAAA,IAER;AAAA,EACF;AACF;AAUO,SAAS,UAAU,UAA4B,CAAC,GAAS;AAC9D,QAAM,SAAS,QAAQ,UAAU,QAAQ,IAAI,iBAAiB;AAE9D,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,UACJ,QAAQ,WAAW,QAAQ,IAAI,iBAAiB;AAElD,QAAM,cAAc,QAAQ,QAAQ,QAAQ,EAAE,IAAI;AAGlD,UAAQ,IAAI,wBAAwB;AACpC,UAAQ,IAAI,sBAAsB;AAElC,QAAM,eACJ,QAAQ,gBAAgB,QAAQ,IAAI,wBAAwB;AAE9D,OAAK,EAAE,aAAa,aAAa,CAAC;AAElC,YAAU,cAAc,QAAQ,QAAQ,QAAQ,UAAU;AAC1D,gBAAc;AAChB;AAOO,SAAS,UAAU,QAA6B;AACrD,MAAI,WAAW,MAAM;AACnB,cAAU;AAAA,EACZ,OAAO;AACL,UAAM,YAAY,eAAe,MAAM;AACvC,cAAU,aAAa;AAAA,EACzB;AACF;AAGO,SAAS,YAA2B;AACzC,SAAO;AACT;AAaO,SAAS,MACd,IACA,UAAwB,CAAC,GACtB;AAEH,QAAM,YAAY,IAAI,SAAuC;AAC3D,UAAM,SAAS,GAAG,GAAG,IAAI;AAGzB,QAAI,kBAAkB,SAAS;AAC7B,aAAO,OAAO,KAAK,CAAC,UAAmB;AACrC,wBAAgB;AAChB,eAAO;AAAA,MACT,CAAC;AAAA,IACH;AAEA,oBAAgB;AAChB,WAAO;AAAA,EACT;AAEA,QAAM,gBAAoC,CAAC;AAC3C,MAAI,QAAQ,KAAM,eAAc,OAAO,QAAQ;AAC/C,MAAI,QAAQ,SAAU,eAAc,WAAW,QAAQ;AACvD,MAAI,QAAQ;AACV,kBAAc,aAAa,QAAQ;AAErC,SAAO,YAAY,WAAgB,aAAa;AAClD;AAaO,SAAS,UAAU,SAA2B;AACnD,QAAM,gBAAmC;AAAA,IACvC,MAAM,QAAQ;AAAA,EAChB;AACA,MAAI,QAAQ,SAAU,eAAc,WAAW,QAAQ;AACvD,MAAI,QAAQ,OAAQ,eAAc,SAAS,QAAQ;AAEnD,QAAM,OAAO,gBAAgB,aAAa;AAG1C,QAAM,cAAc,KAAK,IAAI,KAAK,IAAI;AACtC,OAAK,MAAM,CAAC,eAAgD;AAC1D,oBAAgB;AAChB,WAAO,YAAY,UAAU;AAAA,EAC/B;AAEA,SAAO;AACT;AAGO,SAAS,eAAwB;AACtC,SAAO;AACT;AASA,IAAM,QAAQ;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAO,gBAAQ;","names":["SpanType"]}
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@kayba_ai/tracing",
3
+ "version": "0.1.0",
4
+ "description": "Kayba tracing SDK — instrument your AI agents and send traces to Kayba",
5
+ "license": "MIT",
6
+ "author": "Kayba.ai <hello@kayba.ai>",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/Kayba-ai/agentic-context-engine",
10
+ "directory": "sdk/typescript"
11
+ },
12
+ "homepage": "https://kayba.ai",
13
+ "keywords": [
14
+ "kayba",
15
+ "tracing",
16
+ "mlflow",
17
+ "observability",
18
+ "ai",
19
+ "agents"
20
+ ],
21
+ "main": "./dist/index.js",
22
+ "module": "./dist/index.mjs",
23
+ "types": "./dist/index.d.ts",
24
+ "exports": {
25
+ ".": {
26
+ "types": "./dist/index.d.ts",
27
+ "import": "./dist/index.mjs",
28
+ "require": "./dist/index.js"
29
+ }
30
+ },
31
+ "files": [
32
+ "dist"
33
+ ],
34
+ "publishConfig": {
35
+ "access": "public",
36
+ "provenance": true
37
+ },
38
+ "scripts": {
39
+ "build": "tsup",
40
+ "dev": "tsup --watch",
41
+ "lint": "tsc --noEmit",
42
+ "prepublishOnly": "npm run build"
43
+ },
44
+ "dependencies": {
45
+ "mlflow-tracing": "^0.1.0"
46
+ },
47
+ "devDependencies": {
48
+ "tsup": "^8.0.0",
49
+ "tsx": "^4.21.0",
50
+ "typescript": "^5.5.0"
51
+ },
52
+ "engines": {
53
+ "node": ">=18"
54
+ }
55
+ }