@dbx-tools/appkit 0.9.129 → 0.9.131

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,179 @@
1
+ /** AppKit telemetry compatibility helpers. */
2
+
3
+ import type { IncomingMessage } from "node:http";
4
+ import { createRequire } from "node:module";
5
+ import path from "node:path";
6
+ import { pathToFileURL } from "node:url";
7
+
8
+ import type { Tracer, TracerOptions, TracerProvider } from "@opentelemetry/api";
9
+ import type { SpanProcessor } from "@opentelemetry/sdk-trace-base";
10
+
11
+ type IncomingRequestFilter = (request: IncomingMessage) => boolean;
12
+
13
+ interface NativeHttpInstrumentationConfig {
14
+ readonly enabled?: boolean;
15
+ readonly ignoreIncomingRequestHook?: IncomingRequestFilter;
16
+ readonly [key: string]: unknown;
17
+ }
18
+
19
+ interface NativeInstrumentation {
20
+ setTracerProvider?(provider: TracerProvider): void;
21
+ }
22
+
23
+ interface NativeHttpInstrumentation extends NativeInstrumentation {
24
+ getConfig(): NativeHttpInstrumentationConfig;
25
+ setConfig(config: NativeHttpInstrumentationConfig): void;
26
+ }
27
+
28
+ interface NativeTelemetryManager {
29
+ tracerProvider?: TracerProvider;
30
+ }
31
+
32
+ interface NativeTelemetryManagerClass {
33
+ getInstance(): NativeTelemetryManager;
34
+ registerSpanProcessor(processor: SpanProcessor): void;
35
+ }
36
+
37
+ /** Options for AppKit's native HTTP request tracing. */
38
+ export interface NativeHttpTelemetryOptions {
39
+ /**
40
+ * Request paths to exclude. A trailing `*` matches every path with that
41
+ * prefix; other values are exact path matches. Query strings are ignored.
42
+ */
43
+ readonly exclude?: readonly string[];
44
+ /** Additional caller-owned request filter. Returning `true` excludes the request. */
45
+ readonly filter?: IncomingRequestFilter;
46
+ }
47
+
48
+ /** Return the request pathname without its query string. */
49
+ function requestPath(request: IncomingMessage): string {
50
+ return request.url?.split("?", 1)[0] ?? "";
51
+ }
52
+
53
+ /** Whether one request matches the default or configured HTTP telemetry exclusions. */
54
+ export function excludeHttpTelemetryRequest(
55
+ request: IncomingMessage,
56
+ options: NativeHttpTelemetryOptions = {},
57
+ ): boolean {
58
+ if (request.method === "HEAD") return true;
59
+ const pathname = requestPath(request);
60
+ for (const pattern of options.exclude ?? []) {
61
+ if (pattern.endsWith("*")) {
62
+ if (pathname.startsWith(pattern.slice(0, -1))) return true;
63
+ } else if (pathname === pattern) {
64
+ return true;
65
+ }
66
+ }
67
+ return options.filter?.(request) ?? false;
68
+ }
69
+
70
+ function appKitInternalModuleUrl(relativePath: string): string {
71
+ const require = createRequire(import.meta.url);
72
+ const packageRoot = path.dirname(require.resolve("@databricks/appkit/package.json"));
73
+ return pathToFileURL(path.join(packageRoot, "dist", ...relativePath.split("/"))).href;
74
+ }
75
+
76
+ function isNativeHttpInstrumentation(value: unknown): value is NativeHttpInstrumentation {
77
+ if (!value || typeof value !== "object") return false;
78
+ const candidate = value as Partial<NativeHttpInstrumentation>;
79
+ return typeof candidate.getConfig === "function" && typeof candidate.setConfig === "function";
80
+ }
81
+
82
+ async function nativeInstrumentations(): Promise<Record<string, NativeInstrumentation>> {
83
+ const loaded = (await import(appKitInternalModuleUrl("telemetry/instrumentations.js"))) as {
84
+ instrumentations?: Record<string, NativeInstrumentation>;
85
+ };
86
+ if (!loaded.instrumentations) {
87
+ throw new Error("@databricks/appkit no longer exposes its native instrumentations");
88
+ }
89
+ return loaded.instrumentations;
90
+ }
91
+
92
+ async function nativeHttpInstrumentation(): Promise<NativeHttpInstrumentation> {
93
+ const instrumentation = (await nativeInstrumentations()).http;
94
+ if (!isNativeHttpInstrumentation(instrumentation)) {
95
+ throw new Error(
96
+ "@databricks/appkit no longer exposes the expected native HTTP telemetry instrumentation",
97
+ );
98
+ }
99
+ return instrumentation;
100
+ }
101
+
102
+ async function nativeTelemetryManagerClass(): Promise<NativeTelemetryManagerClass> {
103
+ const loaded = (await import(appKitInternalModuleUrl("telemetry/telemetry-manager.js"))) as {
104
+ TelemetryManager?: NativeTelemetryManagerClass;
105
+ };
106
+ if (!loaded.TelemetryManager) {
107
+ throw new Error("@databricks/appkit no longer exposes its native telemetry manager");
108
+ }
109
+ return loaded.TelemetryManager;
110
+ }
111
+
112
+ async function nativeTelemetryManager(): Promise<NativeTelemetryManager> {
113
+ return (await nativeTelemetryManagerClass()).getInstance();
114
+ }
115
+
116
+ function requireNativeTracerProvider(manager: NativeTelemetryManager): TracerProvider {
117
+ if (!manager.tracerProvider) {
118
+ throw new Error("AppKit's native tracer provider has not started");
119
+ }
120
+ return manager.tracerProvider;
121
+ }
122
+
123
+ /**
124
+ * Extend AppKit's native HTTP request filter without registering a second HTTP
125
+ * instrumentation. AppKit 0.81 owns the instrumentation but does not expose a
126
+ * public filter option, so this compatibility hook mutates its existing
127
+ * singleton before `createApp()` registers it.
128
+ */
129
+ export async function configureNativeHttpTelemetry(
130
+ options: NativeHttpTelemetryOptions = {},
131
+ ): Promise<void> {
132
+ const instrumentation = await nativeHttpInstrumentation();
133
+ const config = instrumentation.getConfig();
134
+ const appKitFilter = config.ignoreIncomingRequestHook;
135
+ instrumentation.setConfig({
136
+ ...config,
137
+ ignoreIncomingRequestHook: (request) =>
138
+ Boolean(appKitFilter?.(request)) || excludeHttpTelemetryRequest(request, options),
139
+ });
140
+ }
141
+
142
+ /**
143
+ * Bind AppKit's native instrumentations to the provider AppKit started. This is
144
+ * called after AppKit's deferred `TelemetryManager.start()` phase so a runtime
145
+ * that already occupied the global OTel slot cannot leave native spans no-op.
146
+ */
147
+ export async function bindNativeTelemetryProvider(): Promise<boolean> {
148
+ const manager = await nativeTelemetryManager();
149
+ if (!manager.tracerProvider) return false;
150
+ for (const instrumentation of Object.values(await nativeInstrumentations())) {
151
+ instrumentation.setTracerProvider?.(manager.tracerProvider);
152
+ }
153
+ return true;
154
+ }
155
+
156
+ /** Contribute a processor before AppKit builds its native tracer provider. */
157
+ export async function registerNativeSpanProcessor(processor: SpanProcessor): Promise<void> {
158
+ (await nativeTelemetryManagerClass()).registerSpanProcessor(processor);
159
+ }
160
+
161
+ /**
162
+ * Return a tracer provider that resolves AppKit's provider when a tracer method
163
+ * is invoked. AppKit starts its provider after plugin setup, while consumers
164
+ * such as Mastra construct their OTel bridge during setup.
165
+ */
166
+ export async function deferredNativeTracerProvider(): Promise<TracerProvider> {
167
+ const manager = await nativeTelemetryManager();
168
+ return {
169
+ getTracer(name: string, version?: string, options?: TracerOptions): Tracer {
170
+ return new Proxy({} as Tracer, {
171
+ get(_target, property) {
172
+ const tracer = requireNativeTracerProvider(manager).getTracer(name, version, options);
173
+ const value = Reflect.get(tracer, property, tracer) as unknown;
174
+ return typeof value === "function" ? value.bind(tracer) : value;
175
+ },
176
+ });
177
+ },
178
+ };
179
+ }
@@ -21,6 +21,8 @@ export interface AgentToolExecutionContext {
21
21
  readonly resourceId?: string;
22
22
  /** Model endpoint selected for the current agent turn. */
23
23
  readonly model?: string;
24
+ /** Browser application origin associated with the current agent turn. */
25
+ readonly origin?: string;
24
26
  /** Best-effort progress sink validated by the hosting integration. */
25
27
  readonly writeProgress?: (event: unknown, options?: AgentToolProgressOptions) => Promise<void>;
26
28
  }