@nekuda/webmcp-sdk 0.4.0-dev.7.3

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/CHANGELOG.md ADDED
@@ -0,0 +1,244 @@
1
+ # Changelog
2
+
3
+ ## Unreleased — usage telemetry schema 2 (breaking wire format)
4
+
5
+ The usage-telemetry channel emits **three events instead of two**, carrying
6
+ derived signals instead of raw page and payload strings. `schema` bumps `1` → `2`.
7
+ Nothing was deployed against `1`, so there is no compatibility shim: an ingest
8
+ reading v1 events reads nothing from this build. `registerTools` behavior, the
9
+ `tracking` channel, and every public API besides the exported event types are
10
+ unchanged. See `docs/telemetry-schema.md`.
11
+
12
+ ### Breaking
13
+
14
+ - **`sdk_init` fires once per page load, not once per `registerTools` call.** It is
15
+ scheduled at import time and flushed on the next task, so it now fires even when
16
+ nobody registers anything — which is the only way a broken integration is
17
+ visible. A page with three `registerTools` calls no longer emits three "init"
18
+ events.
19
+ - **Per-call information moved to the new `tool_registration` event**, one per
20
+ `registerTools` call: `registrationIndex`, `trigger`, `settleMs`, the `config.*`
21
+ booleans (moved off `sdk_init`, which fires before any batch may have run), and
22
+ `tools[]` — the per-tool registration outcomes v1 computed and discarded, so a
23
+ site where 3 of 8 tools fail on a duplicate name is now distinguishable from one
24
+ where all 8 registered. Each entry carries a `schemaHash`, parameter-shape
25
+ metrics, and `descriptionLength` — never a parameter name, description, or schema.
26
+ The event emits when the batch settles, at a 2 s timeout, or on `pagehide` —
27
+ whichever comes first — so a surface whose `registerTool` never resolves still
28
+ reports; tools unsettled at that point carry `outcome: "pending"`, which is not one
29
+ of the registration states `registerTools` itself returns. Each telemetry-enabled
30
+ batch therefore holds one timer and one `{ once: true }` `pagehide` listener until
31
+ it emits, both released on emit.
32
+ - **`tool_call` carries derived signals only.** Added: `callIndex`,
33
+ `toolCallIndex`, `precededBy`, `routeTemplate`, `agentRuntime`,
34
+ `timeSinceInitMs`, `tool.{stableKey,schemaHash,intent}`,
35
+ `response.{bytes,contentBlocks,isError}`, and `errorSignature` (the message with
36
+ quoted literals, opaque tokens, emails, URLs, relative paths, and digit runs
37
+ templated to `*`, so failures cluster and interpolated values do not ship).
38
+ Removed:
39
+ raw `input`, raw `response`, raw `error`, and the whole environment/page block.
40
+ Consequence: it carries no input signal at all in the interim — the
41
+ `schemaValid`/`missingRequired` block needs a JSON-Schema subset validator and is
42
+ deferred.
43
+ - **Every high-cardinality and PII-shaped field is gone**, replaced by a derived
44
+ one: `fullUserAgent` → `client.agentRuntime` + UA-CH brand, `url`/`path` →
45
+ `routeTemplate` (`/products/12345` → `/products/:id`, word slugs kept and anything
46
+ else → `:token`, query and fragment dropped), `referrer` → `referrerClass`,
47
+ `screen` → `formFactor`,
48
+ `language` → its primary subtag, and `timezone`/`platform`/`title` dropped
49
+ outright. They are not allowlist entries set to `false` — they no longer exist,
50
+ so no allowlist change brings them back.
51
+ - **No browser storage anywhere in this channel.** `visitorId` is gone and
52
+ `sessionId` is minted in memory per page load (the ePrivacy Art. 5(3) concern).
53
+ Cross-visit stitching is permanently impossible here; the authenticated
54
+ `tracking` channel keeps its own storage-backed identity and this one never reads
55
+ it. `tracking: { disabled: true }` consequently has nothing to narrow here.
56
+ - **Arrival order is not guaranteed.** `tool_registration` can reach the wire
57
+ before `sdk_init`. Consumers join the three on `sessionId` and must not assume
58
+ ordering.
59
+ - **`TelemetryEvent` is now a discriminated union** of `SdkInitEvent |
60
+ ToolRegistrationEvent | ToolCallEvent`, exported alongside `RegisteredToolEntry`,
61
+ `TelemetryEnvelope`, and the derived value unions (`AgentRuntime`,
62
+ `ReferrerClass`, `SurfaceInfo`, `ToolShapeMetrics`, …). The v1 open event shape
63
+ (`[key: string]: unknown`) is gone, so a field cannot reach the wire with nothing
64
+ declaring it.
65
+
66
+ ### Added
67
+
68
+ - **`globalThis.__WEBMCP_TELEMETRY__ = false`** silences the channel page-wide
69
+ without touching a `registerTools` call site — the only lever a site has when the
70
+ calls come from generated code it does not edit. Strictly `false`, like GPC is
71
+ strictly `true`. It, GPC, and an absent `document` are read at emit time and so
72
+ silence everything; `telemetry: false` cancels `sdk_init` page-wide but reaches the
73
+ other two events per batch — see `docs/telemetry-schema.md` for the exact matrix.
74
+ - **Optional `source` and `intent` on `defineTool`** (`"scanner_generated"` /
75
+ `"merchant_authored"`; `"answer"` / `"act"` / `"transact"`), validated as enums
76
+ and reported per tool. Both stay absent when omitted — absence is the honest
77
+ signal, not a defaulted `merchant_authored`. Both enums are exported from the
78
+ package entry as `ToolSource` / `ToolIntent`.
79
+ - **`x-api-key` on telemetry beacons when the page configures one.** Same
80
+ `/v1/telemetry` path either way; the header only adds tenant attribution, and an
81
+ unkeyed page keeps sending anonymously. Note it makes the request non-simple
82
+ under CORS, so an authenticated beacon costs an `OPTIONS` preflight.
83
+ - **`surface.provenance`** separates a `native` WebMCP surface from a `polyfill` or
84
+ `extension` one (a shim opts in via a `__webmcpProvenance` marker), and
85
+ `sdk.installMode` distinguishes an npm build from a CDN snippet — injected at build
86
+ time via `bun build --define '__WEBMCP_INSTALL_MODE__="cdn_snippet"'`, defaulting to
87
+ `"npm"` for any absent or unrecognized value.
88
+ - **`tools[]` degrades instead of dropping the event.** A batch over the 64 KB
89
+ bound first loses every entry's shape detail, keeping identity and outcome, and
90
+ only then collapses to `{ __truncated, originalBytes, toolCount }` — so "this
91
+ site registered 500 tools" survives even when the entries do not. Both degraded
92
+ shapes are named on the wire contract (`StrippedToolEntry`, `TruncatedTools`), so
93
+ `ToolRegistrationEvent.tools` is a union: narrow with `Array.isArray` before
94
+ reading entries.
95
+ - **Each batch's beacons carry that batch's own `apiKey`.** On a page where two
96
+ tenants each call `registerTools` with their own key, a batch's
97
+ `tool_registration` and `tool_call` authenticate as the tenant that registered
98
+ them rather than as whichever key the page configured last. A keyless batch still
99
+ authenticates as the tenant the page named, and `sdk_init` — which carries page
100
+ context and no tool identity — keeps using the page's key. `precededBy` is scoped
101
+ the same way, being the one field that puts another batch's `stableKey` on this
102
+ batch's event: the call chain breaks where the tenant changes rather than naming
103
+ tenant A's tool in an event signed with tenant B's key.
104
+
105
+ ### Fixed
106
+
107
+ - **The baked ingest host is `ingest.<zone>`, which is the host the backend
108
+ actually serves.** Every published build pointed at `collect.agentlane.com` /
109
+ `collect.agentlane.dev`, and neither name has a DNS record: a dedicated
110
+ `collect.<zone>` host was planned, then dropped in favour of the DNS zone's
111
+ record budget, leaving the backend serving both paths on `ingest.<zone>` while
112
+ the SDK kept shipping the name that was cut. Every beacon on **both** channels —
113
+ `/v1/collect` as well as `/v1/telemetry` — failed at DNS resolution, and
114
+ silently, because the transport swallows every error by design.
115
+
116
+ Verified against dev: `collect.agentlane.dev` does not resolve, `ingest.agentlane.dev`
117
+ does, and the dev publish artifact built from this change delivers all three
118
+ telemetry events (HTTP 200) and lands them in the raw zone unquarantined. The
119
+ in-source fallback, both publish workflows and their baked-host guardrails move
120
+ together. Paths are unchanged and an explicit `endpoint` override still wins.
121
+
122
+ ## 0.4.0 — @nekuda/webmcp-sdk, publishable dual-flavor builds
123
+
124
+ The package is renamed **`@nekuda/webmcp` → `@nekuda/webmcp-sdk`** and becomes
125
+ publishable: prod releases go to public npmjs (tag + human approval), dev
126
+ prereleases to npmjs under the `dev` dist-tag on every merge to `main`.
127
+ Telemetry `sdk.name` and the OTEL logger name follow the rename.
128
+
129
+ ### Changed
130
+
131
+ - **Real ingest domains, baked per flavor.** The placeholder collect/telemetry
132
+ defaults are replaced by `https://collect.agentlane.com` (prod, also the
133
+ in-source fallback) and `https://collect.agentlane.dev` (dev builds), injected
134
+ at build time via `bun build --define __WEBMCP_INGEST_BASE__`. Paths are
135
+ unchanged (`/v1/collect`, `/v1/telemetry`); explicit `endpoint` overrides
136
+ still win.
137
+ - **Dev builds label their exact version.** `sdk.version` in telemetry events is
138
+ injectable via `__WEBMCP_SDK_VERSION__`, so a `0.4.0-dev.N` build no longer
139
+ reports itself as the base release.
140
+ - **Published artifact is `dist/`** — browser ESM bundle plus type declarations
141
+ (`main`/`types`/`exports` now point there; the tarball ships `dist` and this
142
+ changelog only). Relative imports in `src/` carry explicit `.js` extensions so the
143
+ emitted `.d.ts` resolves under `moduleResolution: node16`/`nodenext`; without them
144
+ a Node-ESM consumer with the usual `skipLibCheck: true` silently gets no types at
145
+ all for the whole package.
146
+ - **`@opentelemetry/api-logs` is no longer inlined into the bundle.** The build
147
+ marks it external, restoring the optional-peer design: the guarded lazy import
148
+ resolves the host's copy when installed and no-ops otherwise.
149
+
150
+ ## 0.3.0 — default-on anonymous usage telemetry
151
+
152
+ Adds a second telemetry channel, independent of the opt-in `tracking` channel.
153
+ It is **on by default and needs no `apiKey`**, so it reports from every site the
154
+ SDK runs on. `tracking` behavior is unchanged.
155
+
156
+ ### Added
157
+
158
+ - **Default-on usage telemetry.** One `sdk_init` event per `registerTools` call
159
+ (tools registered, WebMCP availability, browser, `tracking`/`otel`/custom-endpoint
160
+ booleans) and one `tool_call` event per settled invocation (outcome, duration,
161
+ error class). Fire-and-forget, no correlation ID, no batching.
162
+ - **Unauthenticated `/v1/telemetry` endpoint**, separate from `/v1/collect`: the
163
+ request carries no `x-api-key` and no key in the URL or body. As with the collect
164
+ default, the built-in domain is a **placeholder** — no prod telemetry endpoint is
165
+ stood up yet.
166
+ - **`telemetry: false` on `registerTools`** opts a batch out entirely: no events,
167
+ no identity resolution, no storage access, no network.
168
+ - **Global Privacy Control honored.** `navigator.globalPrivacyControl === true`
169
+ silences the channel with no opt-out flag needed.
170
+ - **Browser-only.** With no `document` in scope the channel emits nothing, so a
171
+ module-scope `registerTools` stays silent during SSR/prerender rather than
172
+ beaconing from the consumer's server. Unsupported browsers still report — they
173
+ are missing only `document.modelContext`, which is the adoption signal itself.
174
+ - **`tracking: { disabled: true }` keeps this channel out of browser storage.**
175
+ The two channels share one storage namespace, so a closed consent gate means no
176
+ identity is created, read, or emitted here either — the channel still reports
177
+ the storage-free adoption fields (`telemetry: false` and GPC are its opt-outs).
178
+ A consent-gated tenant also reports `config.trackingEnabled: false`, since that
179
+ channel emits nothing.
180
+ - **`TelemetryEvent` exported** from the entry module.
181
+
182
+ ### Breaking
183
+
184
+ - **`defineTool` rejects a `stableKey` that isn't dot-namespaced `domain.action`**
185
+ (`TypeError`): two or more `[a-z0-9_]+` segments joined by `.`. Closes the gap
186
+ where a `stableKey` copying the wire `name` (e.g. `search_blog_posts`) passed
187
+ validation cleanly — exactly the rename-fragility the field exists to prevent.
188
+
189
+ ### What v1 collects
190
+
191
+ v1 deliberately collects the **superset** of the spec's included and excluded
192
+ field sets: the envelope plus full user agent, language, timezone, screen,
193
+ platform, page fields (origin/url/path/referrer/title), anonymous
194
+ visitor/session identity, and — on `tool_call` — the tool identity, input,
195
+ response, and error message. Payloads are bounded to 64 KB; no stack traces.
196
+ Every field is gated by the typed allowlist in `src/telemetry-fields.ts`, all
197
+ `true` today, so dropping a field is a one-line change plus a release. Disabling
198
+ `visitorId`/`sessionId` there makes the channel storage-free.
199
+
200
+ ## 0.2.0 — the tracking event schema and its transports (breaking)
201
+
202
+ Settles the tool-call event schema and both of its outputs, and adapts the
203
+ backend transport to the deployed ingest contract. Consumers of
204
+ `registerTools({ tracking })` must migrate.
205
+
206
+ ### Added
207
+
208
+ - **`otel: true` on `tracking`** emits each event as an OTEL LogRecord through the
209
+ global `LoggerProvider` (optional peer dependency `@opentelemetry/api-logs`
210
+ `>=0.50.0`; the host app owns exporters). Independent of and composable with the
211
+ backend transport — a call can emit to neither output, either, or both.
212
+ - **`endpoint` on `tracking`** overrides the collect URL.
213
+ - **Optional `ToolDefinition.version`**, emitted as `toolVersion` for drift
214
+ analytics; absent from events when omitted.
215
+ - **`callId`** correlates each invocation's request/response pair, and
216
+ `duration_ms` reports client-measured elapsed time on the response event.
217
+ - **Serialized events bounded to 64 KB** (schema §1.5): `response`, then `input`,
218
+ then `error` are replaced by a `{ __truncated: true, originalBytes }` marker only
219
+ as far as needed to fit, then page strings are sliced.
220
+
221
+ ### Breaking
222
+
223
+ - **The SDK is silent by default.** The 0.1.0 `console.log` tracking stub is gone:
224
+ with neither `apiKey` nor `otel` set, no event is built at all — no identity, no
225
+ storage access, no output. Anything relying on the console output must set `otel`.
226
+ - **`customerId` removed from `TrackingOptions` and the event body.** It was
227
+ required in 0.1.0; the backend now resolves the `api_key` to an `org_id` and
228
+ injects it server-side, so `apiKey` is the sole tenant credential.
229
+ - **Transport is `x-api-key` header + `fetch`, not `?api_key=` + `sendBeacon`.**
230
+ The deployed authorizer's identity source is the `x-api-key` header, which
231
+ `sendBeacon` cannot set, so the beacon path is dropped. Sends now use
232
+ `fetch(endpoint, { keepalive: true, headers: { "x-api-key": … } })` — the key
233
+ travels only in the header, never in the URL or body.
234
+ - **`defineTool` rejects a `stableKey` or `version` over 1024 characters**
235
+ (`TypeError`). They are identity keys copied verbatim onto every event and never
236
+ truncated in flight, so the cap is enforced at authoring time instead.
237
+
238
+ ### Migration
239
+
240
+ - Replace `tracking: { customerId }` with `tracking: { apiKey }`.
241
+ - No prod collect domain is stood up yet: consumers targeting a live backend
242
+ must pass an explicit `endpoint` (e.g. the deployed dev API Gateway URL).
243
+ - Client-side visitor/session storage is now namespaced off a non-reversible
244
+ hash of `apiKey` instead of `customerId`; existing anonymous identities re-mint.
@@ -0,0 +1,79 @@
1
+ import type { ToolAnnotations } from "./spec.js";
2
+ /** How the tool came to exist. Reported on telemetry as `tools[].source`. */
3
+ export type ToolSource = "scanner_generated" | "merchant_authored";
4
+ /** What the tool is for. Reported on telemetry as `tools[].intent`. */
5
+ export type ToolIntent = "answer" | "act" | "transact";
6
+ /** The declared `source`/`intent` values, shared with the telemetry builders. */
7
+ export declare const TOOL_SOURCES: readonly ToolSource[];
8
+ export declare const TOOL_INTENTS: readonly ToolIntent[];
9
+ /**
10
+ * A developer-authored (or plugin-generated) tool declaration. Declaring is
11
+ * side-effect-free — nothing touches the browser until `registerTools`.
12
+ */
13
+ export interface ToolDefinition<TInput extends Record<string, unknown> = Record<string, unknown>> {
14
+ /**
15
+ * Developer-authored durable identity. The WebMCP `name` is the wire identity and
16
+ * may be renamed freely; `stableKey` is what the platform keys on when the site is
17
+ * later connected (analytics continuity, claiming), so it must survive renames and
18
+ * codegen re-runs. It is never sent to the browser API. Enforced shape: dot-namespaced
19
+ * `domain.action` (`[a-z0-9_]+` segments, at least two, joined by `.`) — see
20
+ * `STABLE_KEY_PATTERN`.
21
+ */
22
+ stableKey: string;
23
+ /**
24
+ * WebMCP tool name: 1–128 chars of [A-Za-z0-9_\-.]. Optional — defaults to
25
+ * `stableKey` when omitted, so a tool needs an explicit name only when its wire
26
+ * identity should differ from its durable key.
27
+ */
28
+ name?: string;
29
+ /** Optional human-readable display name. */
30
+ title?: string;
31
+ /** What the tool does, for the agent. Required and non-empty per spec. */
32
+ description: string;
33
+ /** JSON Schema for `execute`'s input, as a plain object. */
34
+ inputSchema?: Record<string, unknown>;
35
+ annotations?: ToolAnnotations;
36
+ /**
37
+ * Optional per-tool version, surfaced on emitted tracking events as `toolVersion`
38
+ * for drift analytics. Free-form string (e.g. semver or a codegen hash); when
39
+ * omitted, `toolVersion` is absent from emitted events (the backend defaults it
40
+ * to `unknown`).
41
+ */
42
+ version?: string;
43
+ /**
44
+ * Optional provenance: was this tool emitted by the scanner or written by hand?
45
+ * Left absent when omitted — the SDK never guesses `merchant_authored`, since
46
+ * absence is the honest signal and the backend can bucket it separately.
47
+ */
48
+ source?: ToolSource;
49
+ /**
50
+ * Optional purpose classification, reported per tool on telemetry. Per-tool
51
+ * rather than per-batch because one tool answers while another transacts.
52
+ */
53
+ intent?: ToolIntent;
54
+ /**
55
+ * The page-owned behavior. May return anything JSON-serializable, a plain string,
56
+ * or a ready-made `{ content: [...] }` result — the SDK normalizes for the agent.
57
+ * Thrown errors propagate to the agent unchanged.
58
+ */
59
+ execute(input: TInput): unknown;
60
+ }
61
+ declare const defined: unique symbol;
62
+ /**
63
+ * A validated, frozen tool — the only thing `registerTools` accepts. `name` is
64
+ * always resolved (falling back to `stableKey`), so it is required here.
65
+ */
66
+ export type WebMCPTool<TInput extends Record<string, unknown> = Record<string, unknown>> = Readonly<ToolDefinition<TInput> & {
67
+ name: string;
68
+ }> & {
69
+ readonly [defined]: true;
70
+ };
71
+ /** `WebMCPTool` erased of its input type, for heterogeneous collections. */
72
+ export type AnyWebMCPTool = WebMCPTool<any>;
73
+ /**
74
+ * Validate and freeze a tool definition. Validation is eager and throws `TypeError`
75
+ * so an invalid tool fails at module-evaluation time (an authoring/codegen bug),
76
+ * not at registration time on some visitor's browser.
77
+ */
78
+ export declare function defineTool<TInput extends Record<string, unknown> = Record<string, unknown>>(definition: ToolDefinition<TInput>): WebMCPTool<TInput>;
79
+ export {};
@@ -0,0 +1,82 @@
1
+ /**
2
+ * @nekuda/webmcp-sdk — the phase-1 WebMCP SDK: a thin wrapper over the plain-JS WebMCP
3
+ * spec (https://webmachinelearning.github.io/webmcp/) for registering and
4
+ * unregistering tools. Plugin-generated code targets THIS surface, never the raw
5
+ * `document.modelContext` API — the wrapper pins a spec version and absorbs the
6
+ * draft's monthly breaking churn (R23).
7
+ *
8
+ * The seam contract (what plugin codegen may rely on):
9
+ *
10
+ * 1. `defineTool(definition)` is side-effect-free: it validates eagerly, freezes,
11
+ * and returns the tool. Nothing touches the browser until `registerTools`.
12
+ * 2. `stableKey` lives on the definition, next to `name`. It is the
13
+ * developer-authored durable identity — it survives renames and codegen re-runs
14
+ * and is never sent to the browser.
15
+ * 3. Registration lifecycle: `registerTools(tools, { signal?, tracking?, telemetry? })`
16
+ * registers on call
17
+ * and returns `{ ready, unregister, signal }`. Unregistration happens ONLY via
18
+ * `unregister()` or the external signal aborting (page teardown / SPA unmount).
19
+ * Browsers without a WebMCP surface are a graceful no-op (`state: "unsupported"`).
20
+ * 4. "Connect later without rewrite": generated modules only `defineTool` and
21
+ * EXPORT tools; one entry module calls `registerTools`. Connecting a site to the
22
+ * platform later (API key, telemetry) changes wrapper internals and config only —
23
+ * generated modules and their imports do not change. See `examples/add-to-cart.ts`.
24
+ * 5. Anonymous tool-call tracking is opt-in via `registerTools`'s `tracking`
25
+ * option (see `TrackingOptions`) and default-silent: with neither `apiKey`
26
+ * nor `otel` set, no event is built at all — no identity resolution, no
27
+ * storage writes, no network, and zero behavior change. When enabled it
28
+ * resolves an anonymous visitor/session identity and emits a
29
+ * request+response event per tool call. The two outputs are independent and
30
+ * composable: `apiKey` POSTs each event to the collect endpoint via `fetch`
31
+ * (`keepalive: true`), authenticated with the `x-api-key` **header** (never a
32
+ * query param or body field); the backend resolves the key to `org_id` and
33
+ * injects it server-side, so the client never sends or knows it. `otel: true`
34
+ * emits each event as a
35
+ * LogRecord through the global OTEL `LoggerProvider` (optional peer dep —
36
+ * the host app owns exporters). `disabled: true` is the hard consent gate for
37
+ * both outputs — but for THIS channel only; the default-on telemetry channel of
38
+ * point 6 has its own opt-out (`telemetry: false`) and `disabled` does not
39
+ * narrow it. See `src/tracking.ts`, `src/transport.ts`, and
40
+ * `examples/add-to-cart.ts`.
41
+ * 6. Anonymous usage telemetry is a SECOND, independent channel: default-ON, so it
42
+ * reports from every site the SDK runs on, not only from `apiKey` tenants. Three
43
+ * events (`TelemetryEvent`), all `schema: 2` and joined on an in-memory
44
+ * `sessionId`: `sdk_init` once per page load, scheduled at *import* time so a
45
+ * site that loads the SDK and never registers is still visible;
46
+ * `tool_registration` once per `registerTools` call, carrying each tool's
47
+ * outcome; and `tool_call` once per settled invocation, as derived signals only —
48
+ * no raw `input`, `response`, or error message, unlike point 5. All three go to a
49
+ * separate `/v1/telemetry` endpoint, fire-and-forget, no batching; arrival order
50
+ * is NOT guaranteed, so consumers join on `sessionId` and never on ordering. A
51
+ * page that configures point 5's `apiKey` has it sent here as `x-api-key` too,
52
+ * which only adds tenant attribution — an unkeyed page sends anonymously to the
53
+ * same path. It composes with point 5: a call can emit to neither channel, either
54
+ * one, or both. Three page-level levers silence it entirely (no event, no
55
+ * network), because all three are read at emit time:
56
+ * `globalThis.__WEBMCP_TELEMETRY__ = false` (strictly `false`), Global Privacy
57
+ * Control (`navigator.globalPrivacyControl === true`), and no `document` in scope —
58
+ * so the module-scope `registerTools` of point 4 stays silent during
59
+ * SSR/prerender instead of beaconing from the consumer's server. A fourth,
60
+ * `telemetry: false` on `registerTools`, silences that batch's `tool_registration`
61
+ * and `tool_call` and cancels `sdk_init` page-wide; see `RegisterToolsOptions` for
62
+ * what that does and does not cover. No browser storage is touched
63
+ * anywhere in this channel: no `visitorId`, no stored `sessionId`, which is why
64
+ * point 5's `disabled` consent gate has nothing to narrow here. An unsupported
65
+ * browser still reports — it is missing only `document.modelContext`, and that
66
+ * fact is itself the adoption signal. Every field is gated by the two baked-in
67
+ * allowlists in `src/telemetry-fields.ts` (one by event path, one by per-tool
68
+ * key; all `true` today), so dropping a field is a one-line change there. See
69
+ * `src/telemetry.ts` and `docs/telemetry-schema.md`.
70
+ * 7. Transport wiring (endpoints, the OTEL logs API, apiKey handling) is
71
+ * wrapper-internal: it is reached only through `TrackingOptions` and the
72
+ * `telemetry` flag, never as a separate export, so connecting a site to the
73
+ * platform stays a config-only change to the entry module (point 4).
74
+ */
75
+ export { type AnyWebMCPTool, type ToolDefinition, type ToolIntent, type ToolSource, type WebMCPTool, defineTool, } from "./define.js";
76
+ export { type RegisterToolsOptions, type ToolRegistration, type ToolRegistrationResult, type ToolRegistrationState, registerTools, } from "./register.js";
77
+ export { type ModelContextLike, type RegisterToolOptions, type SpecTool, type ToolAnnotations, resolveModelContext, } from "./spec.js";
78
+ export type { AgentRuntime, FormFactor, FrameContext, PageVisibility, ReferrerClass, SurfaceGlobal, SurfaceInfo, SurfaceProvenance, } from "./telemetry-context.js";
79
+ export type { ClientContext, InstallMode, PageContext, RegisteredToolEntry, RegistrationTrigger, SdkInfo, SdkInitEvent, StrippedToolEntry, TelemetryEnvelope, TelemetryEvent, TelemetryEventName, ToolCallEvent, ToolCallOutcome, ToolCallResponseMetrics, ToolCallToolInfo, ToolRegistrationEvent, ToolRegistrationOutcome, TrackingConfigInfo, TruncatedTools, } from "./telemetry-events.js";
80
+ /** The per-tool shape metrics `tool_registration` entries inherit as optional. */
81
+ export type { ToolShapeMetrics } from "./tool-metrics.js";
82
+ export type { TrackingEvent, TrackingOptions } from "./tracking.js";