@openattribution/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/LICENSE +190 -0
- package/README.md +243 -0
- package/dist/index.cjs +442 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +440 -0
- package/dist/index.d.ts +440 -0
- package/dist/index.js +410 -0
- package/dist/index.js.map +1 -0
- package/package.json +59 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAttribution Telemetry — TypeScript types.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the Python schema (schema.py) exactly. JSON wire format uses
|
|
5
|
+
* snake_case; these TypeScript types use camelCase with explicit mapping
|
|
6
|
+
* in the client layer.
|
|
7
|
+
*
|
|
8
|
+
* Specification: https://openattribution.org/telemetry
|
|
9
|
+
*/
|
|
10
|
+
/** Supported event types for telemetry tracking. */
|
|
11
|
+
type EventType = "content_retrieved" | "content_displayed" | "content_engaged" | "content_cited" | "turn_started" | "turn_completed" | "product_viewed" | "product_compared" | "cart_add" | "cart_remove" | "checkout_started" | "checkout_completed" | "checkout_abandoned";
|
|
12
|
+
/** Session outcome classifications. */
|
|
13
|
+
type OutcomeType = "conversion" | "abandonment" | "browse";
|
|
14
|
+
/**
|
|
15
|
+
* Privacy levels for conversation data sharing.
|
|
16
|
+
* - `full`: Complete query and response text included.
|
|
17
|
+
* - `summary`: LLM-generated summary of the conversation.
|
|
18
|
+
* - `intent`: Only classified intent/topic, no raw text.
|
|
19
|
+
* - `minimal`: Only metadata (token counts, content URLs).
|
|
20
|
+
*/
|
|
21
|
+
type PrivacyLevel = "full" | "summary" | "intent" | "minimal";
|
|
22
|
+
/** Standardised intent categories for conversation classification. */
|
|
23
|
+
type IntentCategory = "product_research" | "comparison" | "how_to" | "troubleshooting" | "general_question" | "purchase_intent" | "price_check" | "availability_check" | "review_seeking" | "chitchat" | "other";
|
|
24
|
+
/** Actor type for the session initiator. */
|
|
25
|
+
type InitiatorType = "user" | "agent";
|
|
26
|
+
/** How a cited piece of content was used in an agent response. */
|
|
27
|
+
type CitationType = "direct_quote" | "paraphrase" | "reference" | "contradiction";
|
|
28
|
+
/** Prominence of cited content within a response. */
|
|
29
|
+
type CitationPosition = "primary" | "supporting" | "mentioned";
|
|
30
|
+
/** Identity of the initiating agent (when initiator_type is "agent"). */
|
|
31
|
+
interface Initiator {
|
|
32
|
+
agentId?: string;
|
|
33
|
+
manifestRef?: string;
|
|
34
|
+
operatorId?: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* User context for segmentation and attribution.
|
|
38
|
+
* Do not include PII — use hashed or synthetic identifiers.
|
|
39
|
+
*/
|
|
40
|
+
interface UserContext {
|
|
41
|
+
externalId?: string;
|
|
42
|
+
segments?: string[];
|
|
43
|
+
attributes?: Record<string, unknown>;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Captured conversation turn with privacy controls.
|
|
47
|
+
* Populate only the fields appropriate for your privacy level.
|
|
48
|
+
*/
|
|
49
|
+
interface ConversationTurn {
|
|
50
|
+
privacyLevel?: PrivacyLevel;
|
|
51
|
+
queryText?: string;
|
|
52
|
+
responseText?: string;
|
|
53
|
+
queryIntent?: IntentCategory;
|
|
54
|
+
responseType?: string;
|
|
55
|
+
topics?: string[];
|
|
56
|
+
contentUrlsRetrieved?: string[];
|
|
57
|
+
contentUrlsCited?: string[];
|
|
58
|
+
queryTokens?: number;
|
|
59
|
+
responseTokens?: number;
|
|
60
|
+
modelId?: string;
|
|
61
|
+
}
|
|
62
|
+
/** Single telemetry event within a session. */
|
|
63
|
+
interface TelemetryEvent {
|
|
64
|
+
/** Unique event identifier (UUID v4). */
|
|
65
|
+
id: string;
|
|
66
|
+
type: EventType;
|
|
67
|
+
/** UTC timestamp in ISO 8601 format. */
|
|
68
|
+
timestamp: string;
|
|
69
|
+
/** Associated content URL, if applicable. */
|
|
70
|
+
contentUrl?: string;
|
|
71
|
+
/** Associated product UUID, if applicable. */
|
|
72
|
+
productId?: string;
|
|
73
|
+
/** Conversation turn data for turn_started/turn_completed events. */
|
|
74
|
+
turn?: ConversationTurn;
|
|
75
|
+
/** Additional event-specific metadata. */
|
|
76
|
+
data?: Record<string, unknown>;
|
|
77
|
+
}
|
|
78
|
+
/** Session outcome for attribution calculation. */
|
|
79
|
+
interface SessionOutcome {
|
|
80
|
+
type: OutcomeType;
|
|
81
|
+
/** Monetary value in minor currency units (e.g. 4999 = $49.99). */
|
|
82
|
+
valueAmount?: number;
|
|
83
|
+
/** ISO 4217 currency code. Default: "USD". */
|
|
84
|
+
currency?: string;
|
|
85
|
+
/** Product UUIDs involved in the outcome. */
|
|
86
|
+
products?: string[];
|
|
87
|
+
metadata?: Record<string, unknown>;
|
|
88
|
+
}
|
|
89
|
+
/** Options for starting a new session. */
|
|
90
|
+
interface StartSessionOptions {
|
|
91
|
+
contentScope?: string;
|
|
92
|
+
agentId?: string;
|
|
93
|
+
externalSessionId?: string;
|
|
94
|
+
userContext?: UserContext;
|
|
95
|
+
manifestRef?: string;
|
|
96
|
+
priorSessionIds?: string[];
|
|
97
|
+
initiatorType?: InitiatorType;
|
|
98
|
+
initiator?: Initiator;
|
|
99
|
+
}
|
|
100
|
+
/** Complete telemetry session (for bulk upload). */
|
|
101
|
+
interface TelemetrySession {
|
|
102
|
+
schemaVersion?: string;
|
|
103
|
+
sessionId: string;
|
|
104
|
+
initiatorType?: InitiatorType;
|
|
105
|
+
initiator?: Initiator;
|
|
106
|
+
agentId?: string;
|
|
107
|
+
contentScope?: string;
|
|
108
|
+
manifestRef?: string;
|
|
109
|
+
priorSessionIds?: string[];
|
|
110
|
+
startedAt: string;
|
|
111
|
+
endedAt?: string;
|
|
112
|
+
userContext?: UserContext;
|
|
113
|
+
events: TelemetryEvent[];
|
|
114
|
+
outcome?: SessionOutcome;
|
|
115
|
+
}
|
|
116
|
+
/** Options for TelemetryClient. */
|
|
117
|
+
interface TelemetryClientOptions {
|
|
118
|
+
/** Base URL of the OpenAttribution Telemetry server. */
|
|
119
|
+
endpoint: string;
|
|
120
|
+
/** API key sent as X-API-Key header. */
|
|
121
|
+
apiKey?: string;
|
|
122
|
+
/**
|
|
123
|
+
* If true, failed requests are logged and swallowed rather than thrown.
|
|
124
|
+
* Default: true.
|
|
125
|
+
*/
|
|
126
|
+
failSilently?: boolean;
|
|
127
|
+
/** Request timeout in milliseconds. Default: 30_000. */
|
|
128
|
+
timeout?: number;
|
|
129
|
+
/** Maximum retry attempts for transient errors. Default: 3. */
|
|
130
|
+
maxRetries?: number;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* OpenAttribution Telemetry — HTTP client.
|
|
135
|
+
*
|
|
136
|
+
* Zero dependencies — uses native fetch (Node 18+, Deno, browsers, Edge).
|
|
137
|
+
*/
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Async client for recording OpenAttribution telemetry.
|
|
141
|
+
*
|
|
142
|
+
* Works in Node.js ≥ 18, Deno, browsers, and Edge runtimes (Vercel, Cloudflare).
|
|
143
|
+
*
|
|
144
|
+
* @example
|
|
145
|
+
* ```ts
|
|
146
|
+
* const client = new TelemetryClient({
|
|
147
|
+
* endpoint: "https://telemetry.example.com",
|
|
148
|
+
* apiKey: "your-api-key",
|
|
149
|
+
* failSilently: true,
|
|
150
|
+
* });
|
|
151
|
+
*
|
|
152
|
+
* const sessionId = await client.startSession({ contentScope: "my-mix" });
|
|
153
|
+
*
|
|
154
|
+
* await client.recordEvents(sessionId, [
|
|
155
|
+
* { id: crypto.randomUUID(), type: "content_retrieved",
|
|
156
|
+
* timestamp: new Date().toISOString(), contentUrl: "https://..." }
|
|
157
|
+
* ]);
|
|
158
|
+
*
|
|
159
|
+
* await client.endSession(sessionId, { type: "browse" });
|
|
160
|
+
* ```
|
|
161
|
+
*/
|
|
162
|
+
declare class TelemetryClient {
|
|
163
|
+
private readonly endpoint;
|
|
164
|
+
private readonly apiKey;
|
|
165
|
+
private readonly failSilently;
|
|
166
|
+
private readonly timeout;
|
|
167
|
+
private readonly maxRetries;
|
|
168
|
+
constructor(options: TelemetryClientOptions);
|
|
169
|
+
private headers;
|
|
170
|
+
private post;
|
|
171
|
+
/**
|
|
172
|
+
* Start a new telemetry session.
|
|
173
|
+
*
|
|
174
|
+
* @returns Session ID string, or null on silent failure.
|
|
175
|
+
*/
|
|
176
|
+
startSession(options?: StartSessionOptions): Promise<string | null>;
|
|
177
|
+
/**
|
|
178
|
+
* Record a single telemetry event.
|
|
179
|
+
*/
|
|
180
|
+
recordEvent(sessionId: string | null, eventType: EventType, options?: {
|
|
181
|
+
contentUrl?: string;
|
|
182
|
+
productId?: string;
|
|
183
|
+
turn?: ConversationTurn;
|
|
184
|
+
data?: Record<string, unknown>;
|
|
185
|
+
}): Promise<void>;
|
|
186
|
+
/**
|
|
187
|
+
* Record a batch of telemetry events.
|
|
188
|
+
*/
|
|
189
|
+
recordEvents(sessionId: string | null, events: TelemetryEvent[]): Promise<void>;
|
|
190
|
+
/**
|
|
191
|
+
* End a session with an outcome.
|
|
192
|
+
*/
|
|
193
|
+
endSession(sessionId: string | null, outcome: SessionOutcome): Promise<void>;
|
|
194
|
+
/**
|
|
195
|
+
* Upload a complete session in one request (bulk path).
|
|
196
|
+
*
|
|
197
|
+
* Useful for post-hoc reporting or when you've built the session
|
|
198
|
+
* locally and want to submit it in one shot.
|
|
199
|
+
*
|
|
200
|
+
* @returns Server-assigned session ID, or null on silent failure.
|
|
201
|
+
*/
|
|
202
|
+
uploadSession(session: TelemetrySession): Promise<string | null>;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* OpenAttribution Telemetry — MCP session tracker.
|
|
207
|
+
*
|
|
208
|
+
* Provides session continuity across stateless MCP tool calls.
|
|
209
|
+
* The calling agent passes a stable `sessionId` string; this module
|
|
210
|
+
* maps it to an OA session UUID and reuses it across tool calls within
|
|
211
|
+
* the same server process.
|
|
212
|
+
*
|
|
213
|
+
* Usage in an MCP tool:
|
|
214
|
+
*
|
|
215
|
+
* ```ts
|
|
216
|
+
* import { TelemetryClient, MCPSessionTracker } from "@openattribution/telemetry";
|
|
217
|
+
*
|
|
218
|
+
* const client = new TelemetryClient({ endpoint: "...", apiKey: "..." });
|
|
219
|
+
* const tracker = new MCPSessionTracker(client, "my-agent");
|
|
220
|
+
*
|
|
221
|
+
* // In your MCP tool handler:
|
|
222
|
+
* server.tool("search_products", { query: z.string(), sessionId: z.string().optional() },
|
|
223
|
+
* async ({ query, sessionId }) => {
|
|
224
|
+
* const results = await searchProducts(query);
|
|
225
|
+
* await tracker.trackRetrieved(sessionId, results.map(r => r.url));
|
|
226
|
+
* return formatResults(results);
|
|
227
|
+
* }
|
|
228
|
+
* );
|
|
229
|
+
* ```
|
|
230
|
+
*/
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Session tracker for MCP agents.
|
|
234
|
+
*
|
|
235
|
+
* Maintains an in-process mapping of external session IDs to OA session UUIDs.
|
|
236
|
+
* Sessions are created on first use and reused across subsequent tool calls.
|
|
237
|
+
*
|
|
238
|
+
* The in-process registry is intentionally simple — it works correctly for
|
|
239
|
+
* single-process MCP servers. For distributed deployments, pass a shared
|
|
240
|
+
* external store to the constructor.
|
|
241
|
+
*/
|
|
242
|
+
declare class MCPSessionTracker {
|
|
243
|
+
private readonly client;
|
|
244
|
+
private readonly contentScope;
|
|
245
|
+
private readonly registry;
|
|
246
|
+
/**
|
|
247
|
+
* @param client - Configured TelemetryClient instance.
|
|
248
|
+
* @param contentScope - Stable identifier for this agent's content scope
|
|
249
|
+
* (e.g. mix ID, manifest reference, or descriptive slug like "my-shopping-agent").
|
|
250
|
+
*/
|
|
251
|
+
constructor(client: TelemetryClient, contentScope?: string);
|
|
252
|
+
/**
|
|
253
|
+
* Get or create an OA session for the given external session ID.
|
|
254
|
+
*
|
|
255
|
+
* If `externalSessionId` is undefined, a new anonymous session is created
|
|
256
|
+
* on every call (no continuity across tool calls).
|
|
257
|
+
*
|
|
258
|
+
* @returns OA session ID string, or null on silent failure.
|
|
259
|
+
*/
|
|
260
|
+
getOrCreateSession(externalSessionId: string | undefined): Promise<string | null>;
|
|
261
|
+
/**
|
|
262
|
+
* Emit `content_retrieved` events for a list of URLs.
|
|
263
|
+
*
|
|
264
|
+
* Call this after fetching products, search results, or any content
|
|
265
|
+
* that influenced the agent's response.
|
|
266
|
+
*
|
|
267
|
+
* @param externalSessionId - Caller-supplied conversation identifier.
|
|
268
|
+
* @param urls - URLs of content retrieved during this tool call.
|
|
269
|
+
*/
|
|
270
|
+
trackRetrieved(externalSessionId: string | undefined, urls: string[]): Promise<void>;
|
|
271
|
+
/**
|
|
272
|
+
* Emit `content_cited` events for content explicitly referenced in a response.
|
|
273
|
+
*
|
|
274
|
+
* Call this when you know which content the agent cited — e.g. the top
|
|
275
|
+
* search result, an editorial quote, or a product recommendation.
|
|
276
|
+
*
|
|
277
|
+
* @param externalSessionId - Caller-supplied conversation identifier.
|
|
278
|
+
* @param urls - URLs of content cited in the agent's response.
|
|
279
|
+
* @param options - Optional citation metadata.
|
|
280
|
+
*/
|
|
281
|
+
trackCited(externalSessionId: string | undefined, urls: string[], options?: {
|
|
282
|
+
citationType?: "direct_quote" | "paraphrase" | "reference" | "contradiction";
|
|
283
|
+
position?: "primary" | "supporting" | "mentioned";
|
|
284
|
+
}): Promise<void>;
|
|
285
|
+
/**
|
|
286
|
+
* End a session with an outcome.
|
|
287
|
+
*
|
|
288
|
+
* Call this when the conversation concludes — at checkout, after
|
|
289
|
+
* the user clicks a link, or when the session times out.
|
|
290
|
+
*/
|
|
291
|
+
endSession(externalSessionId: string | undefined, outcome: {
|
|
292
|
+
type: "conversion" | "abandonment" | "browse";
|
|
293
|
+
valueAmount?: number;
|
|
294
|
+
currency?: string;
|
|
295
|
+
}): Promise<void>;
|
|
296
|
+
/** Number of active sessions in the registry. */
|
|
297
|
+
get sessionCount(): number;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* OpenAttribution Telemetry — content URL extraction utilities.
|
|
302
|
+
*
|
|
303
|
+
* Helpers for extracting content URLs from AI-generated text, so they
|
|
304
|
+
* can be recorded as telemetry events without manual instrumentation.
|
|
305
|
+
*/
|
|
306
|
+
/**
|
|
307
|
+
* Extract all HTTP/HTTPS URLs from Markdown-formatted text.
|
|
308
|
+
*
|
|
309
|
+
* Finds URLs in two forms:
|
|
310
|
+
* - Markdown links: `[anchor text](https://...)`
|
|
311
|
+
* - Bare URLs: `https://...`
|
|
312
|
+
*
|
|
313
|
+
* Results are deduplicated. Useful for extracting citation URLs from
|
|
314
|
+
* AI model responses that include web search results.
|
|
315
|
+
*
|
|
316
|
+
* @example
|
|
317
|
+
* ```ts
|
|
318
|
+
* const text = "According to [Wirecutter](https://nytimes.com/wirecutter/reviews/...), ...";
|
|
319
|
+
* const urls = extractCitationUrls(text);
|
|
320
|
+
* // ["https://nytimes.com/wirecutter/reviews/..."]
|
|
321
|
+
* ```
|
|
322
|
+
*/
|
|
323
|
+
declare function extractCitationUrls(text: string): string[];
|
|
324
|
+
/**
|
|
325
|
+
* Extract URLs from a list of search result objects.
|
|
326
|
+
*
|
|
327
|
+
* Accepts any object with a `url` string property — works with
|
|
328
|
+
* Channel3, Exa, Tavily, and most search API responses.
|
|
329
|
+
*
|
|
330
|
+
* @example
|
|
331
|
+
* ```ts
|
|
332
|
+
* const products = await channel3.search({ query: "headphones" });
|
|
333
|
+
* const urls = extractResultUrls(products);
|
|
334
|
+
* await tracker.trackRetrieved(sessionId, urls);
|
|
335
|
+
* ```
|
|
336
|
+
*/
|
|
337
|
+
declare function extractResultUrls(results: Array<{
|
|
338
|
+
url?: string | null;
|
|
339
|
+
link?: string | null;
|
|
340
|
+
}>): string[];
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* OpenAttribution Telemetry — ACP (Agentic Commerce Protocol) bridge.
|
|
344
|
+
*
|
|
345
|
+
* Converts a TelemetrySession into the `content_attribution` object
|
|
346
|
+
* defined in the ACP RFC. Include this in a CheckoutSessionCreateRequest
|
|
347
|
+
* or CheckoutSessionCompleteRequest.
|
|
348
|
+
*
|
|
349
|
+
* Reference: acp/rfc.content_attribution.md
|
|
350
|
+
*/
|
|
351
|
+
|
|
352
|
+
interface ContentAttributionRetrieved {
|
|
353
|
+
content_url: string;
|
|
354
|
+
timestamp: string;
|
|
355
|
+
}
|
|
356
|
+
interface ContentAttributionCited {
|
|
357
|
+
content_url: string;
|
|
358
|
+
timestamp: string;
|
|
359
|
+
citation_type?: string;
|
|
360
|
+
excerpt_tokens?: number;
|
|
361
|
+
position?: string;
|
|
362
|
+
content_hash?: string;
|
|
363
|
+
}
|
|
364
|
+
interface ConversationSummary {
|
|
365
|
+
turn_count: number;
|
|
366
|
+
topics: string[];
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* ACP `content_attribution` object.
|
|
370
|
+
* Include in CheckoutSessionCreateRequest.content_attribution.
|
|
371
|
+
*/
|
|
372
|
+
interface ContentAttribution {
|
|
373
|
+
content_scope?: string;
|
|
374
|
+
content_retrieved: ContentAttributionRetrieved[];
|
|
375
|
+
content_cited?: ContentAttributionCited[];
|
|
376
|
+
conversation_summary?: ConversationSummary;
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Convert a TelemetrySession into an ACP `content_attribution` object.
|
|
380
|
+
*
|
|
381
|
+
* @example
|
|
382
|
+
* ```ts
|
|
383
|
+
* import { sessionToContentAttribution } from "@openattribution/telemetry/acp";
|
|
384
|
+
*
|
|
385
|
+
* const attribution = sessionToContentAttribution(session);
|
|
386
|
+
*
|
|
387
|
+
* // Include in ACP checkout request:
|
|
388
|
+
* await acp.createCheckout({
|
|
389
|
+
* cart: { ... },
|
|
390
|
+
* content_attribution: attribution,
|
|
391
|
+
* });
|
|
392
|
+
* ```
|
|
393
|
+
*/
|
|
394
|
+
declare function sessionToContentAttribution(session: TelemetrySession): ContentAttribution;
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* OpenAttribution Telemetry — UCP (Universal Checkout Protocol) bridge.
|
|
398
|
+
*
|
|
399
|
+
* Converts a TelemetrySession into the UCP attribution extension object.
|
|
400
|
+
*
|
|
401
|
+
* Reference: ucp/EXTENSION.md
|
|
402
|
+
*/
|
|
403
|
+
|
|
404
|
+
interface UCPAttribution {
|
|
405
|
+
content_scope?: string;
|
|
406
|
+
prior_session_ids?: string[];
|
|
407
|
+
content_retrieved: Array<{
|
|
408
|
+
content_url: string;
|
|
409
|
+
timestamp: string;
|
|
410
|
+
}>;
|
|
411
|
+
content_cited?: Array<{
|
|
412
|
+
content_url: string;
|
|
413
|
+
timestamp: string;
|
|
414
|
+
citation_type?: string;
|
|
415
|
+
position?: string;
|
|
416
|
+
}>;
|
|
417
|
+
conversation_summary?: {
|
|
418
|
+
turn_count: number;
|
|
419
|
+
topics: string[];
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* Convert a TelemetrySession into a UCP attribution extension object.
|
|
424
|
+
*
|
|
425
|
+
* @example
|
|
426
|
+
* ```ts
|
|
427
|
+
* import { sessionToAttribution } from "@openattribution/telemetry/ucp";
|
|
428
|
+
*
|
|
429
|
+
* const attribution = sessionToAttribution(session);
|
|
430
|
+
*
|
|
431
|
+
* // Include in UCP checkout:
|
|
432
|
+
* await ucp.completeCheckout({
|
|
433
|
+
* order: { ... },
|
|
434
|
+
* extensions: { "org.openattribution.telemetry": attribution },
|
|
435
|
+
* });
|
|
436
|
+
* ```
|
|
437
|
+
*/
|
|
438
|
+
declare function sessionToAttribution(session: TelemetrySession): UCPAttribution;
|
|
439
|
+
|
|
440
|
+
export { type CitationPosition, type CitationType, type ContentAttribution, type ContentAttributionCited, type ContentAttributionRetrieved, type ConversationTurn, type EventType, type Initiator, type InitiatorType, type IntentCategory, MCPSessionTracker, type OutcomeType, type PrivacyLevel, type SessionOutcome, type StartSessionOptions, TelemetryClient, type TelemetryClientOptions, type TelemetryEvent, type TelemetrySession, type UCPAttribution, type UserContext, extractCitationUrls, extractResultUrls, sessionToAttribution, sessionToContentAttribution };
|