@siteverb/webmcp 0.1.0-rc.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.
Files changed (95) hide show
  1. package/README.md +163 -0
  2. package/dist/browser.js +841 -0
  3. package/dist/client.d.ts +3 -0
  4. package/dist/client.d.ts.map +1 -0
  5. package/dist/client.js +320 -0
  6. package/dist/client.js.map +1 -0
  7. package/dist/evals/index.d.ts +13 -0
  8. package/dist/evals/index.d.ts.map +1 -0
  9. package/dist/evals/index.js +20 -0
  10. package/dist/evals/index.js.map +1 -0
  11. package/dist/fingerprint.d.ts +3 -0
  12. package/dist/fingerprint.d.ts.map +1 -0
  13. package/dist/fingerprint.js +33 -0
  14. package/dist/fingerprint.js.map +1 -0
  15. package/dist/id.d.ts +2 -0
  16. package/dist/id.d.ts.map +1 -0
  17. package/dist/id.js +15 -0
  18. package/dist/id.js.map +1 -0
  19. package/dist/index.d.ts +9 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +6 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/src/client.d.ts +3 -0
  24. package/dist/src/client.d.ts.map +1 -0
  25. package/dist/src/client.js +292 -0
  26. package/dist/src/client.js.map +1 -0
  27. package/dist/src/evals/index.d.ts +13 -0
  28. package/dist/src/evals/index.d.ts.map +1 -0
  29. package/dist/src/evals/index.js +20 -0
  30. package/dist/src/evals/index.js.map +1 -0
  31. package/dist/src/fingerprint.d.ts +3 -0
  32. package/dist/src/fingerprint.d.ts.map +1 -0
  33. package/dist/src/fingerprint.js +27 -0
  34. package/dist/src/fingerprint.js.map +1 -0
  35. package/dist/src/index.d.ts +9 -0
  36. package/dist/src/index.d.ts.map +1 -0
  37. package/dist/src/index.js +6 -0
  38. package/dist/src/index.js.map +1 -0
  39. package/dist/src/telemetry.d.ts +21 -0
  40. package/dist/src/telemetry.d.ts.map +1 -0
  41. package/dist/src/telemetry.js +218 -0
  42. package/dist/src/telemetry.js.map +1 -0
  43. package/dist/src/testing/index.d.ts +3 -0
  44. package/dist/src/testing/index.d.ts.map +1 -0
  45. package/dist/src/testing/index.js +2 -0
  46. package/dist/src/testing/index.js.map +1 -0
  47. package/dist/src/testing/memory.d.ts +17 -0
  48. package/dist/src/testing/memory.d.ts.map +1 -0
  49. package/dist/src/testing/memory.js +72 -0
  50. package/dist/src/testing/memory.js.map +1 -0
  51. package/dist/src/transport.d.ts +8 -0
  52. package/dist/src/transport.d.ts.map +1 -0
  53. package/dist/src/transport.js +29 -0
  54. package/dist/src/transport.js.map +1 -0
  55. package/dist/src/types.d.ts +185 -0
  56. package/dist/src/types.d.ts.map +1 -0
  57. package/dist/src/types.js +2 -0
  58. package/dist/src/types.js.map +1 -0
  59. package/dist/src/validation.d.ts +5 -0
  60. package/dist/src/validation.d.ts.map +1 -0
  61. package/dist/src/validation.js +119 -0
  62. package/dist/src/validation.js.map +1 -0
  63. package/dist/src/version.d.ts +2 -0
  64. package/dist/src/version.d.ts.map +1 -0
  65. package/dist/src/version.js +2 -0
  66. package/dist/src/version.js.map +1 -0
  67. package/dist/telemetry.d.ts +21 -0
  68. package/dist/telemetry.d.ts.map +1 -0
  69. package/dist/telemetry.js +276 -0
  70. package/dist/telemetry.js.map +1 -0
  71. package/dist/testing/index.d.ts +3 -0
  72. package/dist/testing/index.d.ts.map +1 -0
  73. package/dist/testing/index.js +2 -0
  74. package/dist/testing/index.js.map +1 -0
  75. package/dist/testing/memory.d.ts +17 -0
  76. package/dist/testing/memory.d.ts.map +1 -0
  77. package/dist/testing/memory.js +72 -0
  78. package/dist/testing/memory.js.map +1 -0
  79. package/dist/transport.d.ts +7 -0
  80. package/dist/transport.d.ts.map +1 -0
  81. package/dist/transport.js +55 -0
  82. package/dist/transport.js.map +1 -0
  83. package/dist/types.d.ts +189 -0
  84. package/dist/types.d.ts.map +1 -0
  85. package/dist/types.js +2 -0
  86. package/dist/types.js.map +1 -0
  87. package/dist/validation.d.ts +5 -0
  88. package/dist/validation.d.ts.map +1 -0
  89. package/dist/validation.js +117 -0
  90. package/dist/validation.js.map +1 -0
  91. package/dist/version.d.ts +2 -0
  92. package/dist/version.d.ts.map +1 -0
  93. package/dist/version.js +2 -0
  94. package/dist/version.js.map +1 -0
  95. package/package.json +57 -0
@@ -0,0 +1,119 @@
1
+ const DEFINED_TOOL = Symbol('siteverb.defined-tool');
2
+ const STABLE_ID_PATTERN = /^[a-z][a-z0-9_-]*(?:\.[a-z][a-z0-9_-]*)+$/;
3
+ const TOOL_NAME_PATTERN = /^[A-Za-z0-9_.-]{1,128}$/;
4
+ function diagnostic(code, message, path, severity) {
5
+ return { code, message, path, severity };
6
+ }
7
+ function inspectParameterDescriptions(value, path, diagnostics) {
8
+ if (value === null || typeof value !== 'object')
9
+ return;
10
+ if (Array.isArray(value)) {
11
+ value.forEach((entry, index) => inspectParameterDescriptions(entry, `${path}[${index}]`, diagnostics));
12
+ return;
13
+ }
14
+ const record = value;
15
+ if (typeof record.description === 'string' && record.description.length > 150) {
16
+ diagnostics.push(diagnostic('parameter-description-budget', 'Parameter descriptions should stay within 150 characters for current agent clients.', `${path}.description`, 'warning'));
17
+ }
18
+ for (const [key, entry] of Object.entries(record)) {
19
+ inspectParameterDescriptions(entry, `${path}.${key}`, diagnostics);
20
+ }
21
+ }
22
+ function inspectAnnotations(annotations, diagnostics) {
23
+ if (annotations === undefined)
24
+ return;
25
+ if ((annotations.readOnlyHint !== undefined && typeof annotations.readOnlyHint !== 'boolean') ||
26
+ (annotations.untrustedContentHint !== undefined &&
27
+ typeof annotations.untrustedContentHint !== 'boolean')) {
28
+ diagnostics.push(diagnostic('invalid-annotations', 'WebMCP annotation hints must be booleans.', 'annotations', 'error'));
29
+ }
30
+ }
31
+ function cloneSchema(schema) {
32
+ if (schema === undefined)
33
+ return undefined;
34
+ const serialized = JSON.stringify(schema);
35
+ if (serialized === undefined) {
36
+ throw new TypeError('inputSchema must be JSON serializable.');
37
+ }
38
+ return JSON.parse(serialized);
39
+ }
40
+ function deepFreeze(value) {
41
+ if (value === null || typeof value !== 'object' || Object.isFrozen(value))
42
+ return value;
43
+ Object.freeze(value);
44
+ for (const nested of Object.values(value))
45
+ deepFreeze(nested);
46
+ return value;
47
+ }
48
+ export function inspectToolDefinition(definition) {
49
+ const diagnostics = [];
50
+ if (typeof definition.id !== 'string' ||
51
+ definition.id.length > 128 ||
52
+ !STABLE_ID_PATTERN.test(definition.id)) {
53
+ diagnostics.push(diagnostic('invalid-stable-id', 'id must be a dot-namespaced stable key such as "catalog.search-products".', 'id', 'error'));
54
+ }
55
+ if (typeof definition.name !== 'string' || !TOOL_NAME_PATTERN.test(definition.name)) {
56
+ diagnostics.push(diagnostic('invalid-tool-name', 'name must contain 1-128 ASCII letters, digits, underscores, hyphens, or periods.', 'name', 'error'));
57
+ }
58
+ else if (definition.name.length > 30) {
59
+ diagnostics.push(diagnostic('tool-name-budget', 'Tool names should stay within 30 characters for current agent clients.', 'name', 'warning'));
60
+ }
61
+ if (typeof definition.description !== 'string' || definition.description.trim() === '') {
62
+ diagnostics.push(diagnostic('invalid-description', 'description must be a non-empty string.', 'description', 'error'));
63
+ }
64
+ else if (definition.description.length > 500) {
65
+ diagnostics.push(diagnostic('description-budget', 'Tool descriptions should stay within 500 characters for current agent clients.', 'description', 'warning'));
66
+ }
67
+ if (definition.title !== undefined && typeof definition.title !== 'string') {
68
+ diagnostics.push(diagnostic('invalid-title', 'title must be a string when provided.', 'title', 'error'));
69
+ }
70
+ if (typeof definition.execute !== 'function') {
71
+ diagnostics.push(diagnostic('invalid-execute', 'execute must be a function.', 'execute', 'error'));
72
+ }
73
+ if (definition.inputSchema !== undefined &&
74
+ (definition.inputSchema === null ||
75
+ typeof definition.inputSchema !== 'object' ||
76
+ Array.isArray(definition.inputSchema))) {
77
+ diagnostics.push(diagnostic('invalid-input-schema', 'inputSchema must be a JSON Schema object when provided.', 'inputSchema', 'error'));
78
+ }
79
+ else if (definition.inputSchema !== undefined) {
80
+ try {
81
+ const serialized = JSON.stringify(definition.inputSchema);
82
+ if (serialized === undefined)
83
+ throw new TypeError('Schema serialized to undefined.');
84
+ inspectParameterDescriptions(definition.inputSchema, 'inputSchema', diagnostics);
85
+ }
86
+ catch {
87
+ diagnostics.push(diagnostic('invalid-input-schema', 'inputSchema must be JSON serializable.', 'inputSchema', 'error'));
88
+ }
89
+ }
90
+ inspectAnnotations(definition.annotations, diagnostics);
91
+ return Object.freeze(diagnostics);
92
+ }
93
+ export function defineTool(definition) {
94
+ const diagnostics = inspectToolDefinition(definition);
95
+ const errors = diagnostics.filter((entry) => entry.severity === 'error');
96
+ if (errors.length > 0) {
97
+ throw new TypeError(errors.map((entry) => `${entry.path}: ${entry.message}`).join('\n'));
98
+ }
99
+ const tool = {
100
+ ...definition,
101
+ ...(definition.inputSchema === undefined
102
+ ? {}
103
+ : { inputSchema: deepFreeze(cloneSchema(definition.inputSchema)) }),
104
+ ...(definition.annotations === undefined
105
+ ? {}
106
+ : { annotations: Object.freeze({ ...definition.annotations }) }),
107
+ };
108
+ Object.defineProperty(tool, DEFINED_TOOL, {
109
+ enumerable: false,
110
+ value: true,
111
+ });
112
+ return Object.freeze(tool);
113
+ }
114
+ export function isDefinedTool(value) {
115
+ return Boolean(value &&
116
+ typeof value === 'object' &&
117
+ value[DEFINED_TOOL] === true);
118
+ }
119
+ //# sourceMappingURL=validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/validation.ts"],"names":[],"mappings":"AAQA,MAAM,YAAY,GAAG,MAAM,CAAC,uBAAuB,CAAC,CAAC;AACrD,MAAM,iBAAiB,GAAG,2CAA2C,CAAC;AACtE,MAAM,iBAAiB,GAAG,yBAAyB,CAAC;AAIpD,SAAS,UAAU,CACjB,IAA4B,EAC5B,OAAe,EACf,IAAY,EACZ,QAAoC;IAEpC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;AAC3C,CAAC;AAED,SAAS,4BAA4B,CACnC,KAAc,EACd,IAAY,EACZ,WAA6B;IAE7B,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO;IACxD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAC7B,4BAA4B,CAAC,KAAK,EAAE,GAAG,IAAI,IAAI,KAAK,GAAG,EAAE,WAAW,CAAC,CACtE,CAAC;QACF,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,KAAgC,CAAC;IAChD,IAAI,OAAO,MAAM,CAAC,WAAW,KAAK,QAAQ,IAAI,MAAM,CAAC,WAAW,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;QAC9E,WAAW,CAAC,IAAI,CACd,UAAU,CACR,8BAA8B,EAC9B,qFAAqF,EACrF,GAAG,IAAI,cAAc,EACrB,SAAS,CACV,CACF,CAAC;IACJ,CAAC;IAED,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,4BAA4B,CAAC,KAAK,EAAE,GAAG,IAAI,IAAI,GAAG,EAAE,EAAE,WAAW,CAAC,CAAC;IACrE,CAAC;AACH,CAAC;AAED,SAAS,kBAAkB,CACzB,WAA8C,EAC9C,WAA6B;IAE7B,IAAI,WAAW,KAAK,SAAS;QAAE,OAAO;IACtC,IACE,CAAC,WAAW,CAAC,YAAY,KAAK,SAAS,IAAI,OAAO,WAAW,CAAC,YAAY,KAAK,SAAS,CAAC;QACzF,CAAC,WAAW,CAAC,oBAAoB,KAAK,SAAS;YAC7C,OAAO,WAAW,CAAC,oBAAoB,KAAK,SAAS,CAAC,EACxD,CAAC;QACD,WAAW,CAAC,IAAI,CACd,UAAU,CACR,qBAAqB,EACrB,2CAA2C,EAC3C,aAAa,EACb,OAAO,CACR,CACF,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,MAA8B;IACjD,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC3C,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAC1C,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,MAAM,IAAI,SAAS,CAAC,wCAAwC,CAAC,CAAC;IAChE,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,CAAe,CAAC;AAC9C,CAAC;AAED,SAAS,UAAU,CAAI,KAAQ;IAC7B,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACxF,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACrB,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;QAAE,UAAU,CAAC,MAAM,CAAC,CAAC;IAC9D,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,UAAkC;IACtE,MAAM,WAAW,GAAqB,EAAE,CAAC;IAEzC,IACE,OAAO,UAAU,CAAC,EAAE,KAAK,QAAQ;QACjC,UAAU,CAAC,EAAE,CAAC,MAAM,GAAG,GAAG;QAC1B,CAAC,iBAAiB,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,EACtC,CAAC;QACD,WAAW,CAAC,IAAI,CACd,UAAU,CACR,mBAAmB,EACnB,2EAA2E,EAC3E,IAAI,EACJ,OAAO,CACR,CACF,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,UAAU,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACpF,WAAW,CAAC,IAAI,CACd,UAAU,CACR,mBAAmB,EACnB,kFAAkF,EAClF,MAAM,EACN,OAAO,CACR,CACF,CAAC;IACJ,CAAC;SAAM,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QACvC,WAAW,CAAC,IAAI,CACd,UAAU,CACR,kBAAkB,EAClB,wEAAwE,EACxE,MAAM,EACN,SAAS,CACV,CACF,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,UAAU,CAAC,WAAW,KAAK,QAAQ,IAAI,UAAU,CAAC,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACvF,WAAW,CAAC,IAAI,CACd,UAAU,CACR,qBAAqB,EACrB,yCAAyC,EACzC,aAAa,EACb,OAAO,CACR,CACF,CAAC;IACJ,CAAC;SAAM,IAAI,UAAU,CAAC,WAAW,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;QAC/C,WAAW,CAAC,IAAI,CACd,UAAU,CACR,oBAAoB,EACpB,gFAAgF,EAChF,aAAa,EACb,SAAS,CACV,CACF,CAAC;IACJ,CAAC;IAED,IAAI,UAAU,CAAC,KAAK,KAAK,SAAS,IAAI,OAAO,UAAU,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC3E,WAAW,CAAC,IAAI,CACd,UAAU,CAAC,eAAe,EAAE,uCAAuC,EAAE,OAAO,EAAE,OAAO,CAAC,CACvF,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,UAAU,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC;QAC7C,WAAW,CAAC,IAAI,CACd,UAAU,CAAC,iBAAiB,EAAE,6BAA6B,EAAE,SAAS,EAAE,OAAO,CAAC,CACjF,CAAC;IACJ,CAAC;IAED,IACE,UAAU,CAAC,WAAW,KAAK,SAAS;QACpC,CAAC,UAAU,CAAC,WAAW,KAAK,IAAI;YAC9B,OAAO,UAAU,CAAC,WAAW,KAAK,QAAQ;YAC1C,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,EACxC,CAAC;QACD,WAAW,CAAC,IAAI,CACd,UAAU,CACR,sBAAsB,EACtB,yDAAyD,EACzD,aAAa,EACb,OAAO,CACR,CACF,CAAC;IACJ,CAAC;SAAM,IAAI,UAAU,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;QAChD,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;YAC1D,IAAI,UAAU,KAAK,SAAS;gBAAE,MAAM,IAAI,SAAS,CAAC,iCAAiC,CAAC,CAAC;YACrF,4BAA4B,CAAC,UAAU,CAAC,WAAW,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC;QACnF,CAAC;QAAC,MAAM,CAAC;YACP,WAAW,CAAC,IAAI,CACd,UAAU,CACR,sBAAsB,EACtB,wCAAwC,EACxC,aAAa,EACb,OAAO,CACR,CACF,CAAC;QACJ,CAAC;IACH,CAAC;IAED,kBAAkB,CAAC,UAAU,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IACxD,OAAO,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,UAAU,CACxB,UAAmD;IAEnD,MAAM,WAAW,GAAG,qBAAqB,CAAC,UAAoC,CAAC,CAAC;IAChF,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC;IACzE,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3F,CAAC;IAED,MAAM,IAAI,GAAG;QACX,GAAG,UAAU;QACb,GAAG,CAAC,UAAU,CAAC,WAAW,KAAK,SAAS;YACtC,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,EAAE,WAAW,EAAE,UAAU,CAAC,WAAW,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC;QACrE,GAAG,CAAC,UAAU,CAAC,WAAW,KAAK,SAAS;YACtC,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;KACI,CAAC;IAEzE,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,YAAY,EAAE;QACxC,UAAU,EAAE,KAAK;QACjB,KAAK,EAAE,IAAI;KACZ,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,CAAyC,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,OAAO,OAAO,CACZ,KAAK;QACH,OAAO,KAAK,KAAK,QAAQ;QACxB,KAA8B,CAAC,YAAY,CAAC,KAAK,IAAI,CACzD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const SITEVERB_WEBMCP_VERSION = "0.1.0";
2
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,uBAAuB,UAAU,CAAC"}
@@ -0,0 +1,2 @@
1
+ export const SITEVERB_WEBMCP_VERSION = '0.1.0';
2
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,uBAAuB,GAAG,OAAO,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { SiteverbOptions, TelemetryErrorClass, TelemetryEventName, TelemetryFlushReason, TelemetryStatus, TelemetryToolIdentity } from './types.js';
2
+ interface EventFields {
3
+ readonly durationMs?: number;
4
+ readonly errorClass?: TelemetryErrorClass;
5
+ readonly invocationId?: string;
6
+ readonly sequenceIndex?: number;
7
+ readonly tool?: TelemetryToolIdentity;
8
+ readonly webmcpSupported?: boolean;
9
+ }
10
+ export interface TelemetryManager {
11
+ readonly enabled: boolean;
12
+ emit(event: TelemetryEventName, fields?: EventFields): void;
13
+ flush(reason?: TelemetryFlushReason): Promise<void>;
14
+ nextSequence(): number;
15
+ status(): TelemetryStatus;
16
+ dispose(): void;
17
+ }
18
+ export declare function createTelemetryManager(options: SiteverbOptions, webmcpSupported: boolean): TelemetryManager;
19
+ export declare function classifyTelemetryError(error: unknown, signal: AbortSignal): TelemetryErrorClass;
20
+ export {};
21
+ //# sourceMappingURL=telemetry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAEV,eAAe,EAGf,mBAAmB,EACnB,kBAAkB,EAClB,oBAAoB,EACpB,eAAe,EACf,qBAAqB,EAEtB,MAAM,YAAY,CAAC;AAGpB,UAAU,WAAW;IACnB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,CAAC,EAAE,mBAAmB,CAAC;IAC1C,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,IAAI,CAAC,EAAE,qBAAqB,CAAC;IACtC,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;CACpC;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,IAAI,CAAC,KAAK,EAAE,kBAAkB,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5D,KAAK,CAAC,MAAM,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,YAAY,IAAI,MAAM,CAAC;IACvB,MAAM,IAAI,eAAe,CAAC;IAC1B,OAAO,IAAI,IAAI,CAAC;CACjB;AAkFD,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,eAAe,EACxB,eAAe,EAAE,OAAO,GACvB,gBAAgB,CAyMlB;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,GAAG,mBAAmB,CAU/F"}
@@ -0,0 +1,276 @@
1
+ import { createFetchTelemetryTransport } from './transport.js';
2
+ import { randomId } from './id.js';
3
+ import { SITEVERB_WEBMCP_VERSION } from './version.js';
4
+ function resolveSessionId(siteId) {
5
+ const key = `__siteverb_session:${siteId}`;
6
+ try {
7
+ const existing = globalThis.sessionStorage?.getItem(key);
8
+ if (existing)
9
+ return existing;
10
+ const created = randomId();
11
+ globalThis.sessionStorage?.setItem(key, created);
12
+ return created;
13
+ }
14
+ catch {
15
+ return randomId();
16
+ }
17
+ }
18
+ function resolveRouteTemplate(route) {
19
+ try {
20
+ return typeof route === 'function' ? route() : route;
21
+ }
22
+ catch {
23
+ return undefined;
24
+ }
25
+ }
26
+ function boundedLabel(value, name, maxLength) {
27
+ if (value === undefined)
28
+ return undefined;
29
+ if (value.length === 0 || value.length > maxLength || /[\u0000-\u001f\u007f]/.test(value)) {
30
+ throw new TypeError(`${name} must contain 1-${maxLength} characters without controls.`);
31
+ }
32
+ return value;
33
+ }
34
+ function safeRouteTemplate(value) {
35
+ if (typeof value !== 'string' ||
36
+ value.length === 0 ||
37
+ value.length > 500 ||
38
+ !value.startsWith('/') ||
39
+ value.startsWith('//') ||
40
+ /[?#\u0000-\u001f\u007f]/.test(value)) {
41
+ return undefined;
42
+ }
43
+ return value;
44
+ }
45
+ function positiveInteger(value, fallback, name) {
46
+ if (value === undefined)
47
+ return fallback;
48
+ if (!Number.isSafeInteger(value) || value <= 0) {
49
+ throw new TypeError(`${name} must be a positive integer.`);
50
+ }
51
+ return value;
52
+ }
53
+ function report(options, diagnostic) {
54
+ try {
55
+ options.onDiagnostic?.(diagnostic);
56
+ }
57
+ catch {
58
+ // Diagnostics must never alter application behavior.
59
+ }
60
+ }
61
+ function disabledManager() {
62
+ return Object.freeze({
63
+ enabled: false,
64
+ emit: () => undefined,
65
+ flush: async () => undefined,
66
+ nextSequence: () => 0,
67
+ status: () => ({
68
+ autoRetryPaused: false,
69
+ consecutiveFailures: 0,
70
+ droppedEvents: 0,
71
+ enabled: false,
72
+ pendingEvents: 0,
73
+ }),
74
+ dispose: () => undefined,
75
+ });
76
+ }
77
+ export function createTelemetryManager(options, webmcpSupported) {
78
+ if (!options.telemetry)
79
+ return disabledManager();
80
+ const siteId = boundedLabel(options.siteId, 'siteId', 128);
81
+ if (!siteId)
82
+ throw new TypeError('siteId is required when telemetry is enabled.');
83
+ const environment = boundedLabel(options.environment, 'environment', 64);
84
+ const release = boundedLabel(options.release, 'release', 200);
85
+ const telemetry = options.telemetry;
86
+ const transport = telemetry.transport ??
87
+ (telemetry.endpoint
88
+ ? createFetchTelemetryTransport({ endpoint: telemetry.endpoint })
89
+ : (() => {
90
+ throw new TypeError('telemetry requires either a transport or endpoint.');
91
+ })());
92
+ const flushIntervalMs = positiveInteger(telemetry.flushIntervalMs, 5_000, 'telemetry.flushIntervalMs');
93
+ const maxBatchSize = positiveInteger(telemetry.maxBatchSize, 20, 'telemetry.maxBatchSize');
94
+ const maxQueueSize = positiveInteger(telemetry.maxQueueSize, 1_000, 'telemetry.maxQueueSize');
95
+ const maxRetryAttempts = positiveInteger(telemetry.maxRetryAttempts, 5, 'telemetry.maxRetryAttempts');
96
+ const retryMaxDelayMs = positiveInteger(telemetry.retryMaxDelayMs, 60_000, 'telemetry.retryMaxDelayMs');
97
+ if (maxBatchSize > maxQueueSize) {
98
+ throw new TypeError('telemetry.maxBatchSize cannot exceed telemetry.maxQueueSize.');
99
+ }
100
+ const pageSessionId = resolveSessionId(siteId);
101
+ let queue = [];
102
+ let pendingBatch;
103
+ let inFlight;
104
+ let timer;
105
+ let disposed = false;
106
+ let autoRetryPaused = false;
107
+ let consecutiveFailures = 0;
108
+ let droppedEvents = 0;
109
+ let eventIndex = 0;
110
+ let sequenceIndex = 0;
111
+ let invalidRouteTemplateReported = false;
112
+ const schedule = (delayMs = flushIntervalMs) => {
113
+ if (disposed || autoRetryPaused || timer || (queue.length === 0 && !pendingBatch))
114
+ return;
115
+ timer = setTimeout(() => {
116
+ timer = undefined;
117
+ void flush('interval').catch(() => undefined);
118
+ }, delayMs);
119
+ };
120
+ const emit = (event, fields = {}) => {
121
+ if (disposed)
122
+ return;
123
+ if (queue.length + (pendingBatch?.events.length ?? 0) >= maxQueueSize) {
124
+ droppedEvents += 1;
125
+ report(options, {
126
+ code: 'telemetry-dropped',
127
+ message: 'A Siteverb telemetry event was dropped because the bounded queue is full.',
128
+ severity: 'warning',
129
+ });
130
+ return;
131
+ }
132
+ const candidateRouteTemplate = resolveRouteTemplate(options.routeTemplate);
133
+ const routeTemplate = safeRouteTemplate(candidateRouteTemplate);
134
+ if (candidateRouteTemplate !== undefined &&
135
+ routeTemplate === undefined &&
136
+ !invalidRouteTemplateReported) {
137
+ invalidRouteTemplateReported = true;
138
+ report(options, {
139
+ code: 'telemetry-route-template-invalid',
140
+ message: 'Siteverb omitted an invalid route template; use a bounded pathname template without query or fragment data.',
141
+ severity: 'warning',
142
+ });
143
+ }
144
+ queue.push(Object.freeze({
145
+ dataClass: 'production',
146
+ event,
147
+ eventId: randomId(),
148
+ eventIndex: eventIndex++,
149
+ occurredAt: new Date().toISOString(),
150
+ pageSessionId,
151
+ ...(environment === undefined ? {} : { environment }),
152
+ ...(release === undefined ? {} : { release }),
153
+ ...(routeTemplate === undefined ? {} : { routeTemplate }),
154
+ ...fields,
155
+ }));
156
+ if (queue.length >= maxBatchSize)
157
+ void flush('size').catch(() => undefined);
158
+ else
159
+ schedule();
160
+ };
161
+ const flush = async (reason = 'manual') => {
162
+ if (timer) {
163
+ clearTimeout(timer);
164
+ timer = undefined;
165
+ }
166
+ if (inFlight) {
167
+ await inFlight;
168
+ if ((reason === 'manual' || reason === 'lifecycle') && queue.length > 0) {
169
+ return flush(reason);
170
+ }
171
+ return;
172
+ }
173
+ if (!pendingBatch && queue.length === 0)
174
+ return;
175
+ if (reason === 'manual' || reason === 'lifecycle')
176
+ autoRetryPaused = false;
177
+ const batch = pendingBatch ??
178
+ Object.freeze({
179
+ batchId: randomId(),
180
+ events: Object.freeze(queue.splice(0, maxBatchSize)),
181
+ protocolVersion: 1,
182
+ sdkVersion: SITEVERB_WEBMCP_VERSION,
183
+ sentAt: new Date().toISOString(),
184
+ siteId,
185
+ });
186
+ pendingBatch = batch;
187
+ const attempt = (async () => {
188
+ try {
189
+ await transport.send(batch, reason);
190
+ if (pendingBatch?.batchId === batch.batchId)
191
+ pendingBatch = undefined;
192
+ consecutiveFailures = 0;
193
+ autoRetryPaused = false;
194
+ }
195
+ catch (cause) {
196
+ consecutiveFailures += 1;
197
+ autoRetryPaused = consecutiveFailures >= maxRetryAttempts;
198
+ report(options, {
199
+ cause,
200
+ code: 'telemetry-send-failed',
201
+ message: autoRetryPaused
202
+ ? 'Siteverb paused automatic telemetry retries; call flush() to retry the retained batch.'
203
+ : 'Siteverb could not deliver a telemetry batch; the same batch will be retried.',
204
+ severity: 'warning',
205
+ });
206
+ if (!autoRetryPaused) {
207
+ schedule(Math.min(flushIntervalMs * 2 ** Math.max(0, consecutiveFailures - 1), retryMaxDelayMs));
208
+ }
209
+ throw cause;
210
+ }
211
+ })();
212
+ let trackedAttempt;
213
+ trackedAttempt = attempt.finally(() => {
214
+ if (inFlight === trackedAttempt)
215
+ inFlight = undefined;
216
+ });
217
+ inFlight = trackedAttempt;
218
+ await trackedAttempt;
219
+ if ((reason === 'manual' || reason === 'lifecycle') && queue.length > 0) {
220
+ return flush(reason);
221
+ }
222
+ schedule();
223
+ };
224
+ const lifecycleFlush = () => {
225
+ void flush('lifecycle').catch(() => undefined);
226
+ };
227
+ const visibilityFlush = () => {
228
+ if (typeof document !== 'undefined' && document.visibilityState === 'hidden')
229
+ lifecycleFlush();
230
+ };
231
+ globalThis.addEventListener?.('pagehide', lifecycleFlush);
232
+ globalThis.document?.addEventListener?.('visibilitychange', visibilityFlush);
233
+ const manager = {
234
+ enabled: true,
235
+ emit,
236
+ flush,
237
+ nextSequence: () => sequenceIndex++,
238
+ status: () => ({
239
+ autoRetryPaused,
240
+ consecutiveFailures,
241
+ droppedEvents,
242
+ enabled: true,
243
+ pendingEvents: queue.length + (pendingBatch?.events.length ?? 0),
244
+ }),
245
+ dispose: () => {
246
+ if (disposed)
247
+ return;
248
+ disposed = true;
249
+ if (timer)
250
+ clearTimeout(timer);
251
+ timer = undefined;
252
+ globalThis.removeEventListener?.('pagehide', lifecycleFlush);
253
+ globalThis.document?.removeEventListener?.('visibilitychange', visibilityFlush);
254
+ lifecycleFlush();
255
+ },
256
+ };
257
+ emit('surface_loaded', { webmcpSupported });
258
+ return Object.freeze(manager);
259
+ }
260
+ export function classifyTelemetryError(error, signal) {
261
+ if (signal.aborted || (error instanceof DOMException && error.name === 'AbortError'))
262
+ return 'abort';
263
+ const name = error instanceof Error ? error.name.toLowerCase().replaceAll(/[-_]/g, '') : '';
264
+ if (name === 'timeouterror')
265
+ return 'timeout';
266
+ if (name === 'networkerror')
267
+ return 'network';
268
+ if (name === 'notfounderror')
269
+ return 'not-found';
270
+ if (name === 'notallowederror' || name === 'securityerror')
271
+ return 'permission';
272
+ if (name === 'validationerror' || name === 'invalidstateerror')
273
+ return 'validation';
274
+ return 'unknown';
275
+ }
276
+ //# sourceMappingURL=telemetry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { createMemoryModelContext, createMemoryTelemetryTransport } from './memory.js';
2
+ export type { MemoryModelContext, MemoryTelemetryTransport } from './memory.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,8BAA8B,EAAE,MAAM,aAAa,CAAC;AACvF,YAAY,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { createMemoryModelContext, createMemoryTelemetryTransport } from './memory.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,8BAA8B,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { NativeModelContext, NativeModelContextTool, NativeRegisteredTool, TelemetryBatch, TelemetryFlushReason, TelemetryTransport } from '../types.js';
2
+ export interface MemoryModelContext extends NativeModelContext {
3
+ readonly registrations: ReadonlyMap<string, NativeModelContextTool>;
4
+ addUninstrumentedTool(tool: NativeRegisteredTool): void;
5
+ executeTool(name: string, input?: Record<string, unknown>, options?: {
6
+ readonly signal?: AbortSignal;
7
+ }): Promise<unknown>;
8
+ }
9
+ export declare function createMemoryModelContext(): MemoryModelContext;
10
+ export interface MemoryTelemetryTransport extends TelemetryTransport {
11
+ readonly batches: readonly TelemetryBatch[];
12
+ readonly reasons: readonly TelemetryFlushReason[];
13
+ failWith(error: unknown): void;
14
+ recover(): void;
15
+ }
16
+ export declare function createMemoryTelemetryTransport(): MemoryTelemetryTransport;
17
+ //# sourceMappingURL=memory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../src/testing/memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,sBAAsB,EAEtB,oBAAoB,EACpB,cAAc,EACd,oBAAoB,EACpB,kBAAkB,EACnB,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,kBAAmB,SAAQ,kBAAkB;IAC5D,QAAQ,CAAC,aAAa,EAAE,WAAW,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC;IACpE,qBAAqB,CAAC,IAAI,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACxD,WAAW,CACT,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAC1C,OAAO,CAAC,OAAO,CAAC,CAAC;CACrB;AAED,wBAAgB,wBAAwB,IAAI,kBAAkB,CAoD7D;AAED,MAAM,WAAW,wBAAyB,SAAQ,kBAAkB;IAClE,QAAQ,CAAC,OAAO,EAAE,SAAS,cAAc,EAAE,CAAC;IAC5C,QAAQ,CAAC,OAAO,EAAE,SAAS,oBAAoB,EAAE,CAAC;IAClD,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IAC/B,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,wBAAgB,8BAA8B,IAAI,wBAAwB,CAoBzE"}
@@ -0,0 +1,72 @@
1
+ export function createMemoryModelContext() {
2
+ const registrations = new Map();
3
+ const uninstrumented = new Map();
4
+ return {
5
+ registrations,
6
+ async registerTool(tool, options) {
7
+ if (registrations.has(tool.name) || uninstrumented.has(tool.name)) {
8
+ throw new DOMException(`Tool "${tool.name}" is already registered.`, 'InvalidStateError');
9
+ }
10
+ if (options?.signal?.aborted)
11
+ throw options.signal.reason;
12
+ registrations.set(tool.name, tool);
13
+ options?.signal?.addEventListener('abort', () => registrations.delete(tool.name), {
14
+ once: true,
15
+ });
16
+ },
17
+ async getTools() {
18
+ return [
19
+ ...Array.from(registrations.values(), (tool) => ({
20
+ name: tool.name,
21
+ title: tool.title ?? '',
22
+ description: tool.description,
23
+ ...(tool.inputSchema === undefined ? {} : { inputSchema: tool.inputSchema }),
24
+ ...(tool.annotations === undefined ? {} : { annotations: tool.annotations }),
25
+ })),
26
+ ...uninstrumented.values(),
27
+ ].sort((left, right) => left.name.localeCompare(right.name));
28
+ },
29
+ addUninstrumentedTool(tool) {
30
+ uninstrumented.set(tool.name, tool);
31
+ },
32
+ async executeTool(name, input = {}, options = {}) {
33
+ const tool = registrations.get(name);
34
+ if (!tool)
35
+ throw new DOMException(`Tool "${name}" was not found.`, 'NotFoundError');
36
+ const controller = new AbortController();
37
+ const onAbort = () => controller.abort(options.signal?.reason);
38
+ if (options.signal?.aborted)
39
+ onAbort();
40
+ else
41
+ options.signal?.addEventListener('abort', onAbort, { once: true });
42
+ try {
43
+ return await tool.execute(input, { signal: controller.signal });
44
+ }
45
+ finally {
46
+ options.signal?.removeEventListener('abort', onAbort);
47
+ }
48
+ },
49
+ };
50
+ }
51
+ export function createMemoryTelemetryTransport() {
52
+ const batches = [];
53
+ const reasons = [];
54
+ let failure;
55
+ return {
56
+ batches,
57
+ reasons,
58
+ send(batch, reason) {
59
+ if (failure !== undefined)
60
+ throw failure;
61
+ batches.push(batch);
62
+ reasons.push(reason);
63
+ },
64
+ failWith(error) {
65
+ failure = error;
66
+ },
67
+ recover() {
68
+ failure = undefined;
69
+ },
70
+ };
71
+ }
72
+ //# sourceMappingURL=memory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.js","sourceRoot":"","sources":["../../src/testing/memory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { TelemetryTransport } from './types.js';
2
+ export interface FetchTelemetryTransportOptions {
3
+ readonly endpoint: string;
4
+ readonly fetch?: typeof globalThis.fetch;
5
+ }
6
+ export declare function createFetchTelemetryTransport(options: FetchTelemetryTransportOptions): TelemetryTransport;
7
+ //# sourceMappingURL=transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAwC,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAE3F,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CAC1C;AAyCD,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,8BAA8B,GACtC,kBAAkB,CAqBpB"}
@@ -0,0 +1,55 @@
1
+ function validateEndpoint(value) {
2
+ if (value.length === 0 ||
3
+ value.length > 2_000 ||
4
+ value !== value.trim() ||
5
+ /[\u0000-\u001f\u007f]/.test(value)) {
6
+ throw new TypeError('Telemetry endpoint must be a bounded URL without controls.');
7
+ }
8
+ if (value.startsWith('/') && !value.startsWith('//')) {
9
+ const base = 'https://siteverb.invalid';
10
+ const resolved = new URL(value, base);
11
+ if (resolved.origin !== base || value.includes('?') || value.includes('#')) {
12
+ throw new TypeError('Telemetry endpoint must not contain query or fragment data.');
13
+ }
14
+ return value;
15
+ }
16
+ let url;
17
+ try {
18
+ url = new URL(value);
19
+ }
20
+ catch {
21
+ throw new TypeError('Telemetry endpoint must be a relative, HTTPS, or loopback HTTP URL.');
22
+ }
23
+ const loopback = url.hostname === 'localhost' || url.hostname === '127.0.0.1' || url.hostname === '[::1]';
24
+ if ((url.protocol !== 'https:' && !(url.protocol === 'http:' && loopback)) ||
25
+ url.username ||
26
+ url.password ||
27
+ url.search ||
28
+ url.hash) {
29
+ throw new TypeError('Telemetry endpoint must use HTTPS or loopback HTTP without credentials, query, or fragment data.');
30
+ }
31
+ return url.href;
32
+ }
33
+ export function createFetchTelemetryTransport(options) {
34
+ if (typeof options.endpoint !== 'string')
35
+ throw new TypeError('A telemetry endpoint is required.');
36
+ const endpoint = validateEndpoint(options.endpoint);
37
+ const fetcher = options.fetch ?? globalThis.fetch?.bind(globalThis);
38
+ return Object.freeze({
39
+ async send(batch, _reason) {
40
+ const body = JSON.stringify(batch);
41
+ if (!fetcher)
42
+ throw new Error('fetch is unavailable for the telemetry transport.');
43
+ const response = await fetcher(endpoint, {
44
+ body,
45
+ credentials: 'omit',
46
+ headers: { 'content-type': 'application/json' },
47
+ keepalive: true,
48
+ method: 'POST',
49
+ });
50
+ if (!response.ok)
51
+ throw new Error(`Telemetry endpoint returned HTTP ${response.status}.`);
52
+ },
53
+ });
54
+ }
55
+ //# sourceMappingURL=transport.js.map