weflayr 0.16.1 → 0.20.2

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,7 @@
1
+ {
2
+ "semi": true,
3
+ "singleQuote": true,
4
+ "trailingComma": "es5",
5
+ "printWidth": 100,
6
+ "tabWidth": 2
7
+ }
package/LICENSE-MIT ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Langfuse GmbH
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/NOTICE ADDED
@@ -0,0 +1,12 @@
1
+ Weflayr Node.js SDK
2
+ Copyright 2026 Weflayr
3
+
4
+ This product includes software derived from langfuse-js
5
+ (https://github.com/langfuse/langfuse-js), Copyright 2024 Langfuse GmbH,
6
+ licensed under the MIT License.
7
+
8
+ Specifically, the OpenTelemetry span filter, span processor, and tag-propagation
9
+ helpers in src/otel/ are derived from langfuse-js packages/otel and packages/core
10
+ and have been adapted for the Weflayr intake API and tag schema.
11
+
12
+ See LICENSE-MIT for the full MIT license text.
@@ -0,0 +1,36 @@
1
+ export default [
2
+ {
3
+ languageOptions: {
4
+ ecmaVersion: 2023,
5
+ sourceType: "commonjs",
6
+ globals: {
7
+ // Node.js
8
+ require: "readonly",
9
+ module: "readonly",
10
+ exports: "writable",
11
+ __dirname: "readonly",
12
+ __filename: "readonly",
13
+ process: "readonly",
14
+ Buffer: "readonly",
15
+ console: "readonly",
16
+ setTimeout: "readonly",
17
+ clearTimeout: "readonly",
18
+ setInterval: "readonly",
19
+ clearInterval: "readonly",
20
+ // Web platform (available in modern Node)
21
+ fetch: "readonly",
22
+ URL: "readonly",
23
+ ReadableStream: "readonly",
24
+ TransformStream: "readonly",
25
+ TextEncoder: "readonly",
26
+ TextDecoder: "readonly",
27
+ },
28
+ },
29
+ rules: {
30
+ "no-unused-vars": ["warn", { argsIgnorePattern: "^_" }],
31
+ "no-undef": "error",
32
+ "prefer-const": "warn",
33
+ eqeqeq: ["error", "smart"],
34
+ },
35
+ },
36
+ ];
package/index.d.ts CHANGED
@@ -1,134 +1,156 @@
1
- /** Arbitrary key-value metadata attached to an LLM call. */
1
+ /** Arbitrary key-value tags applied to OTel spans. */
2
2
  export type Tags = Record<string, string | number | boolean>;
3
3
 
4
4
  /**
5
- * Receives a deep clone of the request args or response, mutates or replaces
6
- * fields, and returns the filtered object sent to the intake API.
5
+ * Span attributes the mask callback can read or scrub. The OpenTelemetry GenAI
6
+ * semantic-convention keys get autocomplete; the index signature catches user
7
+ * tags and provider-specific attributes (e.g. Vercel AI's `ai.*`).
7
8
  */
8
- export type ContentPolicyFn = (data: Record<string, unknown>) => Record<string, unknown>;
9
-
10
- /**
11
- * Extracts extra structured fields merged into the intake event.
12
- * Called with `(args, null)` for the `before` event and `(args, result)` for `after`.
13
- */
14
- export type MiddlewareFn = (
15
- args: Record<string, unknown>,
16
- response: Record<string, unknown> | null,
17
- ) => Record<string, unknown>;
18
-
19
- /** Per-chunk accumulator returned by a `streamMiddleware` factory. */
20
- export interface StreamAccumulator {
21
- /** Return `true` to emit a `stream_pending` event immediately. */
22
- onChunk: (chunk: unknown) => boolean;
23
- /** Called once the stream ends; returns extra fields for the `after` event. */
24
- finalize: () => Record<string, unknown>;
9
+ export interface OtelSpanAttributes {
10
+ 'gen_ai.system'?: string;
11
+ 'gen_ai.operation.name'?: string;
12
+ 'gen_ai.request.model'?: string;
13
+ 'gen_ai.request.temperature'?: number;
14
+ 'gen_ai.request.max_tokens'?: number;
15
+ 'gen_ai.response.model'?: string;
16
+ 'gen_ai.response.id'?: string;
17
+ 'gen_ai.response.finish_reasons'?: string[];
18
+ 'gen_ai.usage.input_tokens'?: number;
19
+ 'gen_ai.usage.output_tokens'?: number;
20
+ /** Only populated when `captureMessageContent=true`. */
21
+ 'gen_ai.prompt'?: string;
22
+ /** Only populated when `captureMessageContent=true`. */
23
+ 'gen_ai.completion'?: string;
24
+ 'gen_ai.tool.name'?: string;
25
+ 'gen_ai.tool.call.id'?: string;
26
+ 'gen_ai.tool.call.arguments'?: string;
27
+ 'error.type'?: string;
28
+ [key: string]: unknown;
25
29
  }
26
30
 
27
- /** Factory called once per stream invocation. */
28
- export type StreamMiddlewareFn = () => StreamAccumulator;
31
+ /** LLM provider SDKs the `autoInstrument` registry knows how to wire up. */
32
+ export const AiSdk: {
33
+ readonly OPENAI: 'openai';
34
+ readonly ANTHROPIC: 'anthropic';
35
+ readonly BEDROCK: 'bedrock';
36
+ readonly AZURE: 'azure';
37
+ readonly COHERE: 'cohere';
38
+ readonly TOGETHER: 'together';
39
+ readonly GOOGLE_VERTEX: 'google-vertex';
40
+ readonly GOOGLE_GENAI: 'google-genai';
41
+ };
42
+ export type AiSdk = (typeof AiSdk)[keyof typeof AiSdk];
29
43
 
30
- /** Instrumentation configuration for a single method path. */
31
- export interface MethodConfig {
32
- /**
33
- * Dot-separated path to the method on the instrumented object
34
- * (e.g. `'chat.completions.create'`), or the function name for bare functions.
35
- */
36
- call: string;
37
- middleware?: MiddlewareFn;
38
- streamMiddleware?: StreamMiddlewareFn;
39
- /**
40
- * Property name on the response object that holds the async iterable stream.
41
- * Use when the SDK returns `{ [streamPath]: AsyncIterable }` instead of a direct AsyncIterable.
42
- * e.g. `'stream'` for AWS Bedrock's `ConverseStreamCommand`.
43
- */
44
- streamPath?: string;
45
- }
44
+ /**
45
+ * Allowed values for `propagateMetadata({ providerName })`: every SDK the
46
+ * auto-instrumentation registry knows, plus providers reached via the OpenAI
47
+ * SDK on the wire but reported as themselves (e.g. Vercel AI Gateway).
48
+ */
49
+ export const AIProviderName: {
50
+ readonly OPENAI: 'openai';
51
+ readonly ANTHROPIC: 'anthropic';
52
+ readonly BEDROCK: 'bedrock';
53
+ readonly AZURE: 'azure';
54
+ readonly COHERE: 'cohere';
55
+ readonly TOGETHER: 'together';
56
+ readonly GOOGLE_VERTEX: 'google-vertex';
57
+ readonly GOOGLE_GENAI: 'google-genai';
58
+ readonly VERCEL_AI_GATEWAY: 'vercel_ai_gateway';
59
+ };
60
+ export type AIProviderName = (typeof AIProviderName)[keyof typeof AIProviderName];
46
61
 
47
- /** Full configuration object passed to `weflayr_setup`. */
48
- export interface WeflayrSettings {
49
- /** Base URL of the Weflayr intake API (e.g. `'https://api.weflayr.com'`). */
50
- intake_url: string;
51
- /** UUID identifying the flayr credential pair. */
52
- client_id: string;
53
- /** Bearer token used when calling the intake API. */
54
- client_secret: string;
55
- /** `'default'` emits before + after events; `'light'` emits only after. */
56
- event_mode?: 'default' | 'light';
57
- /** Set to `false` to disable instrumentation entirely. Defaults to `true`. */
58
- enabled?: boolean;
62
+ export interface SetupOptions {
63
+ /** Weflayr API key. The server resolves your client_id from this token. */
64
+ apiKey: string;
65
+ /** Override the intake base URL. Defaults to WEFLAYR_BASE_URL or https://api.weflayr.com. */
66
+ baseUrl?: string;
67
+ /** Tags applied to every emitted span. */
68
+ defaultTags?: Tags;
59
69
  /**
60
- * Middleware to strip sensitive fields from event payloads before sending to the intake API.
61
- * Mutually exclusive with `allow_fields` setting both blocks all events.
70
+ * `'batch'` (default) groups spans for throughput. `'immediate'` flushes every
71
+ * span synchronously recommended for short-lived runtimes (Lambda, edge).
62
72
  */
63
- ignore_fields?: ContentPolicyFn;
73
+ exportMode?: 'batch' | 'immediate';
64
74
  /**
65
- * Middleware to keep only approved fields in event payloads before sending to the intake API.
66
- * Mutually exclusive with `ignore_fields` setting both blocks all events.
75
+ * When `false`, sets OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=false
76
+ * so instrumentations strip `gen_ai.prompt` / `gen_ai.completion` from spans
77
+ * before they're emitted. Defaults to `true`.
67
78
  */
68
- allow_fields?: ContentPolicyFn;
79
+ captureMessageContent?: boolean;
69
80
  /**
70
- * Static tags attached to every instrumented call. Can be overridden per-call
71
- * via `__weflayr_tags` or at runtime via `weflayr_propagate`.
81
+ * Last-line-of-defense scrubber. Receives the span attribute bag just before
82
+ * export; return the (optionally mutated) bag.
72
83
  */
73
- default_tags?: Tags;
74
- /** Methods to instrument on the proxied object. */
75
- methods?: MethodConfig[];
84
+ mask?: (attrs: OtelSpanAttributes) => OtelSpanAttributes;
76
85
  }
77
86
 
78
- /** Configures weflayr with your credentials and instrumentation settings. */
79
- export function weflayr_setup(settings: WeflayrSettings): void;
80
-
81
- /**
82
- * Wraps an LLM client object or async function so matching method calls emit
83
- * events to the intake API. Returns the original value unchanged when weflayr
84
- * is disabled or the target has no matching method config.
85
- */
86
- export function weflayr_instrument<T>(target: T): T;
87
+ /** Initializes the OpenTelemetry tracer + exporter. Call once at app start. */
88
+ export function setup(options: SetupOptions): void;
87
89
 
88
90
  /**
89
- * Adds or overrides a single key in the runtime default tags.
90
- * Equivalent to adding the key to `default_tags` in `weflayr_setup`, but callable at any
91
- * point during execution (e.g. inside a request handler to propagate a customer ID).
92
- * Propagated tags are overridden by per-call `__weflayr_tags`.
91
+ * Loads and registers OpenTelemetry instrumentation packages for the given provider SDKs.
92
+ * Throws a clear "install package X" error if the matching package isn't installed.
93
+ *
94
+ * @example
95
+ * await weflayr.autoInstrument({ aiSdks: weflayr.AiSdk.OPENAI, apiKey: '...' });
96
+ * await weflayr.autoInstrument({ aiSdks: [weflayr.AiSdk.OPENAI, weflayr.AiSdk.ANTHROPIC] });
93
97
  */
94
- export function weflayr_propagate(key: string, value: string | number | boolean): void;
95
-
96
- /** Sends a custom event to the intake API from user code. No-ops if `weflayr_setup` hasn't been called. */
97
- export function send_event(
98
- eventType: string,
99
- data: Record<string, unknown>,
100
- ): Promise<void> | undefined;
98
+ export function autoInstrument(
99
+ options: { aiSdks: AiSdk | AiSdk[] } & Partial<SetupOptions>
100
+ ): Promise<void>;
101
101
 
102
- /** Options for {@link weflayr_vercel_ai_middleware}. */
103
- export interface WeflayrVercelAiMiddlewareOptions {
104
- /** Static tags attached to every event emitted by this middleware instance. */
105
- tags?: Tags;
102
+ export interface PropagateMetadataOptions {
103
+ /** Product-side feature triggering the LLM call (e.g. `"onboarding-summary"`). */
104
+ featureName: string;
105
+ /** Identifier of the end-user / tenant the call is made for. */
106
+ customerId: string;
107
+ /**
108
+ * Override for the provider seen on the wire. Set this only if it differs
109
+ * from the SDK auto-detected by OpenTelemetry — e.g. calls routed through
110
+ * `vercel_ai_gateway` that proxies to OpenAI/Anthropic but should be
111
+ * reported as the gateway.
112
+ */
113
+ providerName?: AIProviderName;
114
+ /**
115
+ * Arbitrary scalar key/value pairs to attach. Values must be `string`,
116
+ * `number`, or `boolean` so they survive the ClickHouse `Map(String,
117
+ * String)` column they land in. Avoid `featureName` / `customerId` keys
118
+ * here — they have dedicated fields.
119
+ */
120
+ extraTags?: Record<string, string | number | boolean>;
106
121
  }
107
122
 
108
123
  /**
109
- * Returns a Vercel AI SDK `LanguageModelV1Middleware` that emits Weflayr events.
110
- * Requires `weflayr_setup` to have been called first.
124
+ * Attach Weflayr metadata to every LLM span created inside `fn`.
125
+ *
126
+ * Every invocation mints a fresh `uuid` that is stamped on every span inside
127
+ * the scope, so all calls made under one `propagateMetadata` block can be
128
+ * correlated downstream.
111
129
  *
112
130
  * @example
113
- * const model = wrapLanguageModel({
114
- * model: openai('gpt-4o-mini'),
115
- * middleware: weflayr_vercel_ai_middleware({ tags: { feature: 'chat' } }),
116
- * });
131
+ * await weflayr.propagateMetadata(
132
+ * { featureName: 'onboarding', customerId: '#3756', extraTags: { variant: 'control' } },
133
+ * async () => { await openai.chat.completions.create({ ... }); },
134
+ * );
117
135
  */
118
- export function weflayr_vercel_ai_middleware(options?: WeflayrVercelAiMiddlewareOptions): object;
136
+ export function propagateMetadata<T>(
137
+ options: PropagateMetadataOptions,
138
+ fn: () => Promise<T> | T
139
+ ): Promise<T> | T;
119
140
 
120
141
  /**
121
- * Attaches weflayr metadata tags to any SDK call options object.
122
- *
123
- * `__weflayr_tags` is stripped by the instrumented proxy before the real provider call
124
- * is made, so it never reaches the underlying SDK. At runtime this is the identity
125
- * function — the generic signature is its only purpose.
142
+ * Decorator form. Apply to a class method to propagate metadata around every call.
143
+ * Each invocation of the wrapped function mints its own `uuid`.
126
144
  *
127
145
  * @example
128
- * await openai.chat.completions.create(flayred({
129
- * model: 'gpt-4o-mini',
130
- * messages: [...],
131
- * __weflayr_tags: { feature: 'haiku', customer_id: '42' },
132
- * }));
146
+ * class ChatService {
147
+ * @weflayr.propagateMetadata({ featureName: 'chat', customerId: 'user_42' })
148
+ * async reply(userId: string) { ... }
149
+ * }
133
150
  */
134
- export function flayred<T>(options: T & { __weflayr_tags?: Record<string, string | number | boolean> }): T;
151
+ export function propagateMetadata(
152
+ options: PropagateMetadataOptions
153
+ ): <T>(target: T, key?: string, descriptor?: PropertyDescriptor) => T;
154
+
155
+ /** Flush any pending spans. Await before a short-lived runtime exits. */
156
+ export function flush(): Promise<void>;
package/package.json CHANGED
@@ -1,11 +1,15 @@
1
1
  {
2
2
  "name": "weflayr",
3
- "version": "0.16.1",
3
+ "version": "0.20.2",
4
4
  "description": "Weflayr Node.js SDK — instrument any LLM client via JS Proxy",
5
5
  "main": "src/index.js",
6
6
  "types": "index.d.ts",
7
7
  "scripts": {
8
- "test": "node --test tests/index.test.js"
8
+ "test": "node --test tests/index.test.js",
9
+ "lint": "eslint src tests",
10
+ "lint:fix": "eslint src tests --fix",
11
+ "format": "prettier --write src tests",
12
+ "format:check": "prettier --check src tests"
9
13
  },
10
14
  "keywords": [
11
15
  "llm",
@@ -17,5 +21,17 @@
17
21
  "engines": {
18
22
  "node": ">=18.0.0"
19
23
  },
20
- "dependencies": {}
24
+ "dependencies": {
25
+ "@opentelemetry/api": "^1.9.1",
26
+ "@opentelemetry/exporter-trace-otlp-http": "^0.219.0",
27
+ "@opentelemetry/instrumentation": "^0.219.0",
28
+ "@opentelemetry/resources": "^2.8.0",
29
+ "@opentelemetry/sdk-trace-base": "^2.8.0",
30
+ "@opentelemetry/sdk-trace-node": "^2.8.0",
31
+ "async-retry": "^1.3.3"
32
+ },
33
+ "devDependencies": {
34
+ "eslint": "^9.18.0",
35
+ "prettier": "^3.4.2"
36
+ }
21
37
  }
@@ -0,0 +1,114 @@
1
+ 'use strict';
2
+
3
+ const { registerInstrumentations } = require('@opentelemetry/instrumentation');
4
+
5
+ const { debug } = require('./logger');
6
+ const { setup, _state } = require('./setup');
7
+ const { patchOpenAIStreamingUsage } = require('./otel/openai-streaming-usage');
8
+
9
+ const AiSdk = Object.freeze({
10
+ OPENAI: 'openai',
11
+ ANTHROPIC: 'anthropic',
12
+ BEDROCK: 'bedrock',
13
+ AZURE: 'azure',
14
+ COHERE: 'cohere',
15
+ TOGETHER: 'together',
16
+ GOOGLE_VERTEX: 'google-vertex',
17
+ GOOGLE_GENAI: 'google-genai',
18
+ });
19
+
20
+ // Allowed values for `propagateMetadata({ providerName })`: every SDK the
21
+ // auto-instrumentation registry knows, plus providers reached via the OpenAI
22
+ // SDK on the wire but reported as themselves (e.g. Vercel AI Gateway proxies
23
+ // to OpenAI/Anthropic but should be reported as the gateway).
24
+ const AIProviderName = Object.freeze({
25
+ ...AiSdk,
26
+ VERCEL_AI_GATEWAY: 'vercel_ai_gateway',
27
+ });
28
+
29
+ const REGISTRY = {
30
+ [AiSdk.OPENAI]: '@traceloop/instrumentation-openai',
31
+ [AiSdk.ANTHROPIC]: '@traceloop/instrumentation-anthropic',
32
+ [AiSdk.BEDROCK]: '@traceloop/instrumentation-bedrock',
33
+ [AiSdk.AZURE]: '@traceloop/instrumentation-azure',
34
+ [AiSdk.COHERE]: '@traceloop/instrumentation-cohere',
35
+ [AiSdk.TOGETHER]: '@traceloop/instrumentation-together',
36
+ [AiSdk.GOOGLE_VERTEX]: '@traceloop/instrumentation-vertexai',
37
+ [AiSdk.GOOGLE_GENAI]: '@traceloop/instrumentation-google-generativeai',
38
+ };
39
+
40
+ const SETUP_OPTION_KEYS = [
41
+ 'apiKey',
42
+ 'baseUrl',
43
+ 'defaultTags',
44
+ 'exportMode',
45
+ 'mask',
46
+ 'captureMessageContent',
47
+ 'warnOnExportError',
48
+ ];
49
+
50
+ function _instantiateInstrumentation(instrumentationPkg) {
51
+ for (const value of Object.values(instrumentationPkg)) {
52
+ if (typeof value === 'function' && /Instrumentation$/.test(value.name)) {
53
+ return new value();
54
+ }
55
+ }
56
+ if (typeof instrumentationPkg.default === 'function') return new instrumentationPkg.default();
57
+ throw new Error('No Instrumentation class found in module exports');
58
+ }
59
+
60
+ async function _instrumentAiSdk(aiSdk) {
61
+ if (!(aiSdk in REGISTRY)) {
62
+ throw new Error(
63
+ `weflayr.autoInstrument: unknown provider "${aiSdk}". Known: ${Object.keys(REGISTRY).join(', ')}`
64
+ );
65
+ }
66
+ const pkg = REGISTRY[aiSdk];
67
+
68
+ let instrumentationPkg;
69
+ try {
70
+ instrumentationPkg = require(pkg);
71
+ } catch (err) {
72
+ throw new Error(
73
+ `weflayr.autoInstrument("${aiSdk}"): failed to load "${pkg}". ` +
74
+ `Install it with: npm install ${pkg}\nUnderlying error: ${err.message}`
75
+ );
76
+ }
77
+
78
+ const instrumentation = _instantiateInstrumentation(instrumentationPkg);
79
+ if (aiSdk === AiSdk.OPENAI) {
80
+ // The OpenAI instrumentor drops token usage on streamed calls; backfill it.
81
+ patchOpenAIStreamingUsage(instrumentation);
82
+ }
83
+ registerInstrumentations({ instrumentations: [instrumentation] });
84
+ debug('autoInstrument: registered aiSdk=%s package=%s', aiSdk, pkg);
85
+ }
86
+
87
+ /**
88
+ * Register an OTel Instrumentor for one or more LLM provider SDKs.
89
+ *
90
+ * Convenience: pass `apiKey` (+ other `setup()` options) here to skip a
91
+ * separate `weflayr.setup()` call. If `apiKey` is omitted, `setup()` must
92
+ * have been called beforehand.
93
+ */
94
+ async function autoInstrument({ aiSdks, ...options } = {}) {
95
+ if (aiSdks === undefined) {
96
+ throw new Error('weflayr.autoInstrument: `aiSdks` is required.');
97
+ }
98
+
99
+ if (!_state.processor) {
100
+ // setup() picks up WEFLAYR_API_KEY from the env if not passed here.
101
+ const setupOptions = {};
102
+ for (const key of SETUP_OPTION_KEYS) {
103
+ if (options[key] !== undefined) setupOptions[key] = options[key];
104
+ }
105
+ setup(setupOptions);
106
+ }
107
+
108
+ const list = Array.isArray(aiSdks) ? aiSdks : [aiSdks];
109
+ for (const aiSdk of list) {
110
+ await _instrumentAiSdk(aiSdk);
111
+ }
112
+ }
113
+
114
+ module.exports = { autoInstrument, AiSdk, AIProviderName, REGISTRY };
package/src/index.js CHANGED
@@ -1,36 +1,14 @@
1
1
  'use strict';
2
2
 
3
- const { configure, weflayr_instrument, weflayr_propagate, send_event } = require('./instrument');
4
- const { weflayr_vercel_ai_middleware } = require('./vercel-ai-middleware');
5
-
6
- /**
7
- *
8
- * @param {*} settings: settings for weflayr
9
- * @returns
10
- */
11
- function weflayr_setup(settings) {
12
- if (settings.enabled === false) return;
13
-
14
- const { intake_url, client_id, client_secret } = settings;
15
-
16
- if (!intake_url || !client_id || !client_secret) {
17
- throw new Error(
18
- 'Weflayr: intake_url, client_id and client_secret must be set in settings'
19
- );
20
- }
21
-
22
- configure(intake_url, client_id, client_secret, settings);
23
- }
24
-
25
- /**
26
- * Attaches weflayr metadata tags to any SDK call options object.
27
- *
28
- * @template T
29
- * @param {T & { __weflayr_tags?: Record<string, string | number | boolean> }} options
30
- * @returns {T}
31
- */
32
- function flayred(options) {
33
- return options;
34
- }
35
-
36
- module.exports = { weflayr_setup, weflayr_instrument, weflayr_propagate, send_event, flayred, weflayr_vercel_ai_middleware };
3
+ const { setup, flush } = require('./setup');
4
+ const { autoInstrument, AiSdk, AIProviderName } = require('./auto-instrument');
5
+ const { propagateMetadata } = require('./otel/propagation');
6
+
7
+ module.exports = {
8
+ setup,
9
+ flush,
10
+ autoInstrument,
11
+ AiSdk,
12
+ AIProviderName,
13
+ propagateMetadata,
14
+ };
package/src/logger.js ADDED
@@ -0,0 +1,8 @@
1
+ 'use strict';
2
+
3
+ const { debuglog } = require('node:util');
4
+
5
+ // Enable with NODE_DEBUG=weflayr
6
+ const debug = debuglog('weflayr');
7
+
8
+ module.exports = { debug };