@webex/internal-plugin-metrics 3.12.0 → 3.13.0-next.1

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 (98) hide show
  1. package/.repo-context.json +466 -0
  2. package/.sdd/manifest.json +626 -0
  3. package/AGENTS.md +208 -0
  4. package/README.md +274 -0
  5. package/dist/automated-user.js +19 -0
  6. package/dist/automated-user.js.map +1 -0
  7. package/dist/batcher.js +3 -0
  8. package/dist/batcher.js.map +1 -1
  9. package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js +639 -66
  10. package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js.map +1 -1
  11. package/dist/call-diagnostic/call-diagnostic-metrics.js +240 -103
  12. package/dist/call-diagnostic/call-diagnostic-metrics.js.map +1 -1
  13. package/dist/call-diagnostic/call-diagnostic-metrics.util.js +7 -2
  14. package/dist/call-diagnostic/call-diagnostic-metrics.util.js.map +1 -1
  15. package/dist/call-diagnostic/config.js +19 -4
  16. package/dist/call-diagnostic/config.js.map +1 -1
  17. package/dist/config.js +8 -0
  18. package/dist/config.js.map +1 -1
  19. package/dist/index.js +25 -1
  20. package/dist/index.js.map +1 -1
  21. package/dist/metrics.js +118 -5
  22. package/dist/metrics.js.map +1 -1
  23. package/dist/metrics.types.js +4 -0
  24. package/dist/metrics.types.js.map +1 -1
  25. package/dist/network-telemetry.js +610 -0
  26. package/dist/network-telemetry.js.map +1 -0
  27. package/dist/new-metrics.js +63 -17
  28. package/dist/new-metrics.js.map +1 -1
  29. package/dist/privacy-and-security-permission-enricher/constants.js +18 -0
  30. package/dist/privacy-and-security-permission-enricher/constants.js.map +1 -0
  31. package/dist/privacy-and-security-permission-enricher/index.js +143 -0
  32. package/dist/privacy-and-security-permission-enricher/index.js.map +1 -0
  33. package/dist/privacy-and-security-permission-enricher/types.js +7 -0
  34. package/dist/privacy-and-security-permission-enricher/types.js.map +1 -0
  35. package/dist/privacy-and-security-permission-enricher/utils.js +71 -0
  36. package/dist/privacy-and-security-permission-enricher/utils.js.map +1 -0
  37. package/dist/types/automated-user.d.ts +2 -0
  38. package/dist/types/call-diagnostic/call-diagnostic-metrics-latencies.d.ts +208 -5
  39. package/dist/types/call-diagnostic/call-diagnostic-metrics.d.ts +83 -17
  40. package/dist/types/call-diagnostic/config.d.ts +6 -0
  41. package/dist/types/config.d.ts +9 -0
  42. package/dist/types/index.d.ts +5 -3
  43. package/dist/types/metrics.types.d.ts +11 -5
  44. package/dist/types/network-telemetry.d.ts +108 -0
  45. package/dist/types/new-metrics.d.ts +17 -1
  46. package/dist/types/privacy-and-security-permission-enricher/constants.d.ts +6 -0
  47. package/dist/types/privacy-and-security-permission-enricher/index.d.ts +40 -0
  48. package/dist/types/privacy-and-security-permission-enricher/types.d.ts +14 -0
  49. package/dist/types/privacy-and-security-permission-enricher/utils.d.ts +5 -0
  50. package/dist/types/unhandled-exception-telemetry/index.d.ts +60 -0
  51. package/dist/types/unhandled-exception-telemetry/utils.d.ts +6 -0
  52. package/dist/unhandled-exception-telemetry/index.js +331 -0
  53. package/dist/unhandled-exception-telemetry/index.js.map +1 -0
  54. package/dist/unhandled-exception-telemetry/utils.js +105 -0
  55. package/dist/unhandled-exception-telemetry/utils.js.map +1 -0
  56. package/docs/adr/index.md +27 -0
  57. package/docs/architecture.md +437 -0
  58. package/docs/getting-started.md +131 -0
  59. package/docs/index.md +52 -0
  60. package/docs/specs/README.md +88 -0
  61. package/package.json +12 -11
  62. package/schemas/repo-context.schema.json +796 -0
  63. package/src/automated-user.ts +16 -0
  64. package/src/batcher.js +4 -0
  65. package/src/call-diagnostic/call-diagnostic-metrics-latencies.ts +801 -74
  66. package/src/call-diagnostic/call-diagnostic-metrics.ts +184 -42
  67. package/src/call-diagnostic/call-diagnostic-metrics.util.ts +7 -1
  68. package/src/call-diagnostic/config.ts +16 -0
  69. package/src/call-diagnostic/docs/README.md +535 -0
  70. package/src/config.js +8 -0
  71. package/src/docs/README.md +703 -0
  72. package/src/index.ts +16 -0
  73. package/src/metrics.js +123 -5
  74. package/src/metrics.types.ts +29 -6
  75. package/src/network-telemetry.ts +757 -0
  76. package/src/new-metrics.ts +56 -6
  77. package/src/privacy-and-security-permission-enricher/constants.ts +33 -0
  78. package/src/privacy-and-security-permission-enricher/docs/README.md +356 -0
  79. package/src/privacy-and-security-permission-enricher/index.ts +142 -0
  80. package/src/privacy-and-security-permission-enricher/types.ts +21 -0
  81. package/src/privacy-and-security-permission-enricher/utils.ts +82 -0
  82. package/src/rtcMetrics/docs/README.md +447 -0
  83. package/src/unhandled-exception-telemetry/docs/README.md +536 -0
  84. package/src/unhandled-exception-telemetry/index.ts +404 -0
  85. package/src/unhandled-exception-telemetry/utils.ts +101 -0
  86. package/test/unit/spec/automated-user.ts +43 -0
  87. package/test/unit/spec/batcher.js +43 -0
  88. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-batcher.ts +14 -2
  89. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-latencies.ts +1435 -304
  90. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.ts +1265 -207
  91. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.util.ts +27 -0
  92. package/test/unit/spec/metrics.js +14 -5
  93. package/test/unit/spec/network-telemetry.ts +610 -0
  94. package/test/unit/spec/new-metrics.ts +203 -50
  95. package/test/unit/spec/prelogin-metrics-batcher.ts +71 -36
  96. package/test/unit/spec/privacy-and-security-permission-enricher.ts +318 -0
  97. package/test/unit/spec/unhandled-exception-telemetry/utils.ts +109 -0
  98. package/test/unit/spec/unhandled-exception-telemetry.ts +689 -0
package/AGENTS.md ADDED
@@ -0,0 +1,208 @@
1
+ <!-- sdd-generated-metadata
2
+ doc_kind: agent-entry
3
+ generated_from: agents@0.3.0
4
+ generated_by: claude-code
5
+ approved_by: rarajes2@cisco.com
6
+ updated_at: 2026-10-07T04:50:31Z
7
+ validation_status: pass
8
+ -->
9
+
10
+ # AI Agent Instructions
11
+
12
+ Agent entry for the `@webex/internal-plugin-metrics` package inside the `webex-js-sdk` monorepo.
13
+ Commands in this file are run from the monorepo root unless stated otherwise.
14
+
15
+ ## Working Method
16
+
17
+ - Read the relevant repository files before editing. Do not edit blind.
18
+ - Understand the task and affected surfaces before writing code.
19
+ - Prefer focused edits over rewriting whole files.
20
+ - Do not invent commands, paths, exports, or behavior. Verify them from repository-local source.
21
+ - Test or validate before declaring done.
22
+ - Keep output concise. If something is uncertain, say so instead of guessing.
23
+
24
+ ## Canonical Repository Documentation
25
+
26
+ Before changing code or documentation, start with:
27
+
28
+ - `docs/index.md` for repository documentation navigation;
29
+ - `docs/architecture.md` for repository boundaries and interactions;
30
+ - `docs/specs/README.md` for the manifest-backed module and contract registry;
31
+ - the affected module's manifest-routed `<module-path>/docs/README.md`; and
32
+ - `docs/adr/index.md` plus applicable concrete ADRs for durable decisions.
33
+
34
+ Follow `.sdd/manifest.json` for each contract's publication state and canonical source. Published
35
+ repository-owned HTTP APIs use their linked OpenAPI document; internal HTTP surfaces may link route
36
+ code, and published SDKs use their ecosystem-native API artifact. The manifest remains authoritative
37
+ for canonical paths and artifact decisions.
38
+
39
+ This package owns no HTTP surface. Every HTTP contract it touches belongs to the upstream Webex
40
+ metrics or unified telemetry service, and its own published surface is the SDK export declared in
41
+ `package.json` and `src/index.ts`.
42
+
43
+ ## 1. Commands (Run First)
44
+
45
+ Use only documented commands. Do not invent alternatives when a command is missing.
46
+
47
+ | Task | Command |
48
+ | ---------------------- | --------------------------------------------------------------------------------- |
49
+ | Install dependencies | `yarn install` (monorepo root) |
50
+ | Start dev environment | Not applicable — this package is a library plugin with no runnable dev server |
51
+ | Run tests | `yarn workspace @webex/internal-plugin-metrics test:unit` |
52
+ | Run linters | `yarn workspace @webex/internal-plugin-metrics test:style` |
53
+ | Build/release artifact | `yarn workspace @webex/internal-plugin-metrics build:src` |
54
+ | Format code | No dedicated command; `test:style` runs `eslint ./src/**/*.*` without `--fix` |
55
+
56
+ Run a single unit spec with `--targets` relative to `test/unit/spec/`, for example
57
+ `yarn workspace @webex/internal-plugin-metrics test:unit --targets network-telemetry.ts`.
58
+
59
+ There is no runnable full build-with-tests command. The `test` script in `package.json` chains
60
+ `test:integration` and `test:browser`, which this package does not define, and no `test/integration`
61
+ directory exists. `.sdd/manifest.json` records `commands.build` as an unresolved owner decision for that
62
+ reason. Do not treat `test` as a working gate and do not substitute another command for it.
63
+
64
+ If a required command is unknown, stop and ask for the exact command.
65
+
66
+ ## 2. Agent Persona and Scope
67
+
68
+ You are the Webex JS SDK telemetry engineering assistant for `@webex/internal-plugin-metrics`.
69
+
70
+ Primary outcomes:
71
+
72
+ - Deliver production-safe changes with passing tests.
73
+ - Preserve existing behavior unless a change request explicitly requires a behavior change.
74
+ - Keep docs and configuration aligned with code changes.
75
+
76
+ Definition of done:
77
+
78
+ 1. Requested change is implemented.
79
+ 2. Relevant tests/lint/build checks pass locally.
80
+ 3. Updated docs/config cover new behavior.
81
+ 4. PR summary includes risks and rollback notes.
82
+
83
+ ## 3. Repository Knowledge
84
+
85
+ ### Tech Stack
86
+
87
+ Document concrete versions so assistants choose compatible APIs.
88
+
89
+ | Area | Tooling | Version |
90
+ | ---------------- | ------------------------------------------------------------ | ------------------------------ |
91
+ | Language runtime | Node.js; `engines` in `package.json` sets the consumer floor, and the owner-declared manifest `toolchain` sets the build and test version | `22.14` to build and test; `>=18` floor |
92
+ | Build tool | `@webex/legacy-tools` plus `tsc`, per `package.json` scripts | workspace package |
93
+ | Test framework | Mocha, selected by `webex-legacy-tools test --runner mocha` | workspace runner |
94
+ | Lint/format | ESLint with `@webex/eslint-config-legacy`, per `.eslintrc.js` | `eslint ^8.24.0`, `prettier ^2.7.1` |
95
+
96
+ ### Project Map
97
+
98
+ - `src/index.ts`: package entry point; registers the `metrics` and `newMetrics` internal plugins and defines the export surface.
99
+ - `src/metrics.js`: the legacy `webex.internal.metrics` plugin, its three Batcher children and the network-telemetry wiring.
100
+ - `src/new-metrics.ts`: the `webex.internal.newMetrics` façade over every current event family.
101
+ - `src/network-telemetry.ts`: the SDK request-outcome collector and its summary payload.
102
+ - `src/call-diagnostic/`: Call Analyzer client, feature and media-quality events, the latency ledger and error-code mapping.
103
+ - `src/privacy-and-security-permission-enricher/`: permission-change enrichment policy for client events.
104
+ - `src/rtcMetrics/`: WebRTC stats reporting to the unified telemetry service.
105
+ - `src/unhandled-exception-telemetry/`: browser uncaught-error and rejection reporter.
106
+ - `test/unit/spec/`: the unit suite; its subtree mirrors `src/`.
107
+
108
+ ### Critical Constraints
109
+
110
+ - The Call Analyzer event schema is owned externally by `@webex/event-dictionary-ts`, pinned in `package.json`. Do not hand-declare event names or payload fields in `src/metrics.types.ts`; derive them from that package.
111
+ - Telemetry must never affect the requests it observes. Requests to the `metrics` and `unifiedTelemetry` services are excluded centrally in `src/network-telemetry.ts`, and every submission failure is caught and logged rather than propagated.
112
+ - Personal data must not reach telemetry. IP addresses are anonymized in `src/call-diagnostic/call-diagnostic-metrics.util.ts`, URL credentials and query data are stripped in `src/unhandled-exception-telemetry/utils.ts`, and endpoint path segments are redacted in `src/network-telemetry.ts`.
113
+ - `webex.internal.metrics` and `webex.internal.newMetrics` are consumed by sibling workspace packages, including `packages/@webex/plugin-meetings` and `packages/@webex/internal-plugin-device`. Treat both surfaces as stable and additive.
114
+ - `src/metrics.js` must tolerate being constructed standalone and before `webex.config` is populated. Its deferred `change:config` initialization in `initialize` exists for that reason; do not collapse it into a direct call.
115
+
116
+ ## 4. Testing Workflow
117
+
118
+ Run checks in this order:
119
+
120
+ 1. `yarn workspace @webex/internal-plugin-metrics test:unit`
121
+ 2. `yarn workspace @webex/internal-plugin-metrics test:style`
122
+ 3. Not applicable — this package defines no integration or end-to-end tier.
123
+
124
+ Testing rules:
125
+
126
+ - Add or update tests for every behavior change.
127
+ - Cover failure paths and edge cases, not only happy paths.
128
+ - Do not remove tests to make CI pass.
129
+ - Use `sinon` for stubs and `assert` from `@webex/test-helper-chai` for assertions, matching the existing specs.
130
+ - Control time with `sinon.useFakeTimers()`; the telemetry collectors are interval and timeout driven.
131
+
132
+ ## 5. Code Style and Patterns
133
+
134
+ Coding expectations:
135
+
136
+ - Follow repository style rules and static analysis output.
137
+ - Prefer small, composable functions over large procedural blocks.
138
+ - Make error handling explicit at system boundaries.
139
+ - Keep public interfaces stable unless a breaking change is requested.
140
+ - Before adding a literal path, filename, command, workflow identifier, status,
141
+ or other policy value, search the repository for exact and semantically
142
+ equivalent uses. When repeated production values represent one shared
143
+ contract, move them to the narrowest owning shared module or catalog as one
144
+ canonical named constant, enum, or type and update consumers. Keep incidental
145
+ similarities, one-off implementation details, and independent test fixtures
146
+ local.
147
+ - Do not import a default, named, object, or namespace binding and immediately
148
+ re-export it. Consumers should import from the owning module; package barrels
149
+ should use direct named re-exports.
150
+ - Do not write inline runtime `typeof` checks outside descriptively named guard
151
+ implementations. Import and reuse the owning guard instead; TypeScript
152
+ type-position `typeof` queries remain allowed.
153
+
154
+ Pattern example:
155
+
156
+ ```text
157
+ Preferred:
158
+ - Validate external input close to the boundary.
159
+ - Return typed/structured results.
160
+ - Include actionable error messages.
161
+
162
+ Avoid:
163
+ - Passing unvalidated payloads deep into the system.
164
+ - Swallowing exceptions or returning ambiguous null values.
165
+ ```
166
+
167
+ New code in this package is TypeScript. `src/metrics.js`, `src/batcher.js`,
168
+ `src/client-metrics-batcher.js` and `src/config.js` remain JavaScript because they extend the
169
+ Ampersand-based `WebexPlugin` and `Batcher` classes from `@webex/webex-core`; keep edits there
170
+ in-style rather than converting the file as a side effect.
171
+
172
+ ## 6. Git Workflow
173
+
174
+ - Branch naming: `[feature|fix|chore]/[short-description]`
175
+ - Commit format: conventional commits (`feat:`, `fix:`, `docs:`, `refactor:`, `test:`, `chore:`)
176
+ - Keep commits focused and reversible.
177
+ - Rebase on the target branch before opening PR.
178
+
179
+ PR checklist:
180
+
181
+ - What changed and why.
182
+ - Tests run and results.
183
+ - Risk/impact areas.
184
+ - Rollback approach.
185
+
186
+ ## 7. Boundaries and Escalation
187
+
188
+ ### Always
189
+
190
+ - Prefer existing patterns over introducing new architecture.
191
+ - Keep changes minimal for the requested scope.
192
+ - Call out assumptions and unknowns explicitly.
193
+
194
+ ### Ask First
195
+
196
+ - Adding new dependencies or external services.
197
+ - Large refactors or schema migrations.
198
+ - Security-sensitive changes (auth, encryption, secrets handling).
199
+ - Any destructive data or infrastructure operation.
200
+ - Changing a submitted payload shape, metric name or event name, because downstream ingestion and dashboards depend on them.
201
+
202
+ ### Never
203
+
204
+ - Commit secrets, keys, or credentials.
205
+ - Bypass required checks by disabling tests or linters.
206
+ - Rewrite history on shared branches.
207
+ - Change unrelated files "while here" without clear need.
208
+ - Add personally identifiable information, credentials or raw IP addresses to any telemetry payload.
package/README.md CHANGED
@@ -8,6 +8,8 @@ This is an internal Cisco Webex plugin. As such, it does not strictly adhere to
8
8
 
9
9
  - [Install](#install)
10
10
  - [Usage](#usage)
11
+ - [Unhandled exception telemetry](#unhandled-exception-telemetry)
12
+ - [Network request telemetry](#network-request-telemetry)
11
13
  - [Contribute](#contribute)
12
14
  - [Maintainers](#maintainers)
13
15
  - [License](#license)
@@ -29,6 +31,278 @@ const webex = new WebexCore();
29
31
  webex.internal.metrics.WHATEVER;
30
32
  ```
31
33
 
34
+ ## Unhandled exception telemetry
35
+
36
+ Unhandled exception telemetry is currently supported only in browser environments. It starts after
37
+ the Webex SDK emits `ready`. It does not install a standalone collector, capture errors before SDK
38
+ initialization, persist events, or retry failed telemetry submissions.
39
+
40
+ The reporter captures uncaught errors, unhandled promise rejections, and resource load failures.
41
+ Matching failures captured in the same one-second in-memory window are submitted once with an
42
+ `occurrenceCount`. Non-HTTP(S) URLs are redacted; URL credentials, query parameters, and fragments
43
+ are stripped; and error names, messages, and stacks are truncated before submission.
44
+
45
+ Telemetry is disabled by default. Enable it with
46
+ `metrics.unhandledExceptionTelemetry.enabled: true`. Applications may provide a synchronous
47
+ `getMetadata` callback in the same configuration object. It must return an object whose fields can
48
+ include application context such as `orgId` and `dataCenter`. Metadata must not contain personally
49
+ identifiable information or credentials.
50
+
51
+ ````js
52
+ import Webex from 'webex';
53
+
54
+ const webex = Webex.init({
55
+ config: {
56
+ metrics: {
57
+ unhandledExceptionTelemetry: {
58
+ enabled: true,
59
+ getMetadata: () => ({
60
+ orgId: 'your-organization-id',
61
+ dataCenter: 'your-data-center',
62
+ }),
63
+ },
64
+ },
65
+ },
66
+ });
67
+ ## Network request telemetry
68
+
69
+ Network request telemetry is disabled by default. Enable it with
70
+ `metrics.networkTelemetry.enabled: true`. When enabled, the metrics plugin summarizes requests
71
+ made through the Webex SDK request pipeline. The reporting interval is configurable with
72
+ `metrics.networkTelemetry.intervalMs` and defaults to ten minutes. It listens to the SDK-wide `request:start`,
73
+ `request:success`, and `request:failure` events, so individual plugins do not need to wrap or
74
+ replace `webex.request()`.
75
+
76
+ For example, to collect one-minute windows:
77
+
78
+ ```js
79
+ const webex = Webex.init({
80
+ config: {
81
+ metrics: {
82
+ networkTelemetry: {
83
+ enabled: true,
84
+ intervalMs: 60 * 1_000,
85
+ },
86
+ },
87
+ },
88
+ });
89
+ ```
90
+
91
+ The listeners are installed once for each Webex instance when `webex.internal.metrics` is
92
+ constructed and the feature is enabled. The metrics package must be imported before constructing
93
+ the Webex instance. Standard Webex SDK bundles already import and register the metrics plugin.
94
+
95
+ ### Scope
96
+
97
+ The collector counts request and response outcomes that pass through `webex.request()` and its interceptors. For failures, it also records aggregated error details covering:
98
+
99
+ - HTTP responses rejected by the SDK, such as `4xx` and `5xx` responses.
100
+ - Network or CORS failures where no HTTP response is available.
101
+ - Aborted and timed-out SDK requests when the error exposes that information.
102
+ - Request preparation failures that emit `request:failure`.
103
+
104
+ It does not monitor arbitrary application `fetch()`, `XMLHttpRequest`, WebSocket, or other traffic outside the SDK request pipeline. It also does not use `PerformanceObserver` or browser-wide request interception.
105
+
106
+ ### Event flow
107
+
108
+ ```text
109
+ webex.request()
110
+ -> SDK request interceptors
111
+ -> request:start(options)
112
+ -> request:success(options, response) or request:failure(options, reason)
113
+ -> metrics request outcome listeners
114
+ -> aggregate host, endpoint, response, and error counts
115
+ -> every configured interval, submit JS_SDK_NETWORK_REQUEST_SUMMARY
116
+ ````
117
+
118
+ The listeners and ten-minute accumulator are registered during metrics plugin initialization:
119
+
120
+ ```js
121
+ initialize(...args) {
122
+ WebexPlugin.prototype.initialize.call(this, ...args);
123
+ if (this.webex.config.metrics.networkTelemetry.enabled !== true) {
124
+ return;
125
+ }
126
+ this.networkTelemetry = createNetworkTelemetryCollector(/* submission callbacks */);
127
+ this.listenTo(this.webex, 'request:start', this.recordNetworkRequestStart);
128
+ this.listenTo(this.webex, 'request:success', this.recordNetworkRequestSuccess);
129
+ this.listenTo(this.webex, 'request:failure', this.recordNetworkRequestFailure);
130
+ }
131
+ ```
132
+
133
+ The metrics plugin exposes `flushNetworkTelemetry()` for callers that need to submit the current
134
+ non-empty window immediately, such as after an early call failure. When the metrics plugin is
135
+ stopped, any non-empty partial window is submitted once before the collector is disposed. Empty
136
+ windows are not submitted during shutdown, and the shutdown hook waits for the submission attempt
137
+ to settle.
138
+
139
+ ```js
140
+ await webex.internal.metrics.flushNetworkTelemetry();
141
+ ```
142
+
143
+ ### Metric schema
144
+
145
+ One operational client metric named `JS_SDK_NETWORK_REQUEST_SUMMARY` is submitted at the configured
146
+ interval. Its `eventPayload` has this shape:
147
+
148
+ ```ts
149
+ type NetworkTelemetry = {
150
+ metricsSummary: {
151
+ totalSendRequest: number;
152
+ totalFailedRequest: number;
153
+ totalRecvdResponse: number;
154
+ totalFailedResponse: number;
155
+ };
156
+ metrics: Array<{
157
+ host: string;
158
+ endPoint: string;
159
+ countSendRequest: number;
160
+ countFailedRequest: number;
161
+ countRecvdResponse: number;
162
+ countFailedResponse: number;
163
+ averageNetworkDurationMs: number;
164
+ maxNetworkDurationP90Ms: number;
165
+ maxNetworkDurationP99Ms: number;
166
+ }>;
167
+ errorMetrics: Array<{
168
+ host: string;
169
+ endPoint: string;
170
+ statusCode: number;
171
+ errorCode: string;
172
+ method: string;
173
+ errorType: string;
174
+ errorMessage: string;
175
+ trackingIds: string[];
176
+ countError: number;
177
+ }>;
178
+ errorMetricsSummary: Record<string, {count: number}>;
179
+ };
180
+ ```
181
+
182
+ The SDK adds application metadata to the outer client metric when it wraps this `eventPayload`:
183
+
184
+ | Property | Source |
185
+ | -------------------- | --------------------------------------------------------------------------- |
186
+ | `tags.app_name` | `webex.config.appName`, or `unknown` |
187
+ | `tags.app_version` | `webex.config.appVersion`, or `unknown` |
188
+ | `tags.app_url` | Browser origin without path/query data, hostname fallback, or `non-browser` |
189
+ | `fields.sdk_version` | `webex.version` |
190
+
191
+ Counter mapping:
192
+
193
+ | Event or outcome | Summary and endpoint counters |
194
+ | --------------------------------------------------- | --------------------------------------------------------------------------- |
195
+ | `request:start` | `totalSendRequest`, `countSendRequest` |
196
+ | `request:success` | `totalRecvdResponse`, `countRecvdResponse` |
197
+ | `request:failure` without an HTTP response | `totalFailedRequest`, `countFailedRequest` |
198
+ | `request:failure` with an HTTP status (`4xx`/`5xx`) | Received-response counters plus `totalFailedResponse`/`countFailedResponse` |
199
+
200
+ The `metrics` array is grouped by `host` and `endPoint`. For service-based SDK requests, `host` is the normalized logical service name. Direct-URI requests use the URI host. `endPoint` is a sanitized resource or URI path. `averageNetworkDurationMs` is the average measured network duration for completed requests in the group, while `maxNetworkDurationP90Ms` and `maxNetworkDurationP99Ms` are the maximum durations at the nearest-rank 90th and 99th percentiles. All values are in milliseconds.
201
+
202
+ The `errorMetrics` array groups identical failures by host, endpoint, status code, error code, method, error type, and error message. `countError` records the number of occurrences, while `trackingIds` retains at most ten unique identifiers. `errorMetricsSummary` counts errors by status code; status `0` means no HTTP response was available.
203
+
204
+ Example:
205
+
206
+ ```js
207
+ {
208
+ metricName: 'JS_SDK_NETWORK_REQUEST_SUMMARY',
209
+ type: 'operational',
210
+ fields: {
211
+ totalSendRequest: 14,
212
+ totalFailedRequest: 1,
213
+ totalRecvdResponse: 13,
214
+ totalFailedResponse: 1
215
+ },
216
+ eventPayload: {
217
+ metricsSummary: {
218
+ totalSendRequest: 14,
219
+ totalFailedRequest: 1,
220
+ totalRecvdResponse: 13,
221
+ totalFailedResponse: 1
222
+ },
223
+ metrics: [{
224
+ host: 'hydra',
225
+ endPoint: 'rooms/:id/messages',
226
+ countSendRequest: 2,
227
+ countFailedRequest: 0,
228
+ countRecvdResponse: 2,
229
+ countFailedResponse: 1,
230
+ averageNetworkDurationMs: 410,
231
+ maxNetworkDurationP90Ms: 510,
232
+ maxNetworkDurationP99Ms: 640
233
+ }],
234
+ errorMetrics: [{
235
+ host: 'hydra',
236
+ endPoint: 'rooms/:id/messages',
237
+ statusCode: 503,
238
+ errorCode: 'SERVICE_UNAVAILABLE',
239
+ method: 'POST',
240
+ errorType: 'server_error',
241
+ errorMessage: 'Service unavailable',
242
+ trackingIds: ['example-tracking-id'],
243
+ countError: 1
244
+ }],
245
+ errorMetricsSummary: {
246
+ 503: {count: 1}
247
+ }
248
+ }
249
+ }
250
+ ```
251
+
252
+ ### Failure classification
253
+
254
+ Classification is evaluated in the following order:
255
+
256
+ | Condition | `errorType` |
257
+ | --------------------------------------------------------------------------------------------------------- | --------------- |
258
+ | Error name is `AbortError` | `aborted` |
259
+ | Status is `408` or `504`, timeout appears in the error details, or the configured request timeout elapsed | `timeout` |
260
+ | Status is `429` | `rate_limited` |
261
+ | Status is `5xx` | `server_error` |
262
+ | Status is `4xx` | `client_error` |
263
+ | No response status is available, or the error name contains `network` | `network_error` |
264
+ | Any other SDK request failure | `request_error` |
265
+
266
+ ### Telemetry request exclusion
267
+
268
+ Requests to the `metrics` and `unifiedTelemetry` services are excluded from both success and failure collection. The exclusion also covers the legacy `api: 'metrics'` request option. This prevents a telemetry upload from affecting its own summary.
269
+
270
+ The exclusion is centralized in the collector; telemetry request call sites do not require special flags.
271
+
272
+ ### Endpoint normalization and cardinality
273
+
274
+ The `endPoint` value is derived from `options.resource`, or from the URI path for a direct-URI request:
275
+
276
+ - Query parameters and fragments are removed.
277
+ - Numeric, percent-encoded, uppercase, and otherwise non-route-looking segments are replaced with `:id`.
278
+
279
+ For example:
280
+
281
+ ```text
282
+ rooms/Y2lzY29zcGFyazovL3VzL1JPT00/messages?personId=secret
283
+ ```
284
+
285
+ becomes:
286
+
287
+ ```text
288
+ rooms/:id/messages
289
+ ```
290
+
291
+ Endpoint normalization is heuristic. A short lowercase alphabetic identifier can resemble a static route segment. Do not place sensitive values directly in a resource path; use normal SDK resource identifiers and avoid embedding credentials or personal data in route names. Error messages are included because they are part of the requested error aggregate schema; callers should not put credentials or personal data in thrown error messages.
292
+
293
+ ### Submission behavior
294
+
295
+ Each ten-minute summary uses the existing `submitClientMetrics()` batching and transport path. The accumulator resets at the reporting boundary before asynchronous submission, so requests received while a summary is being sent belong to the next window. A telemetry submission failure is caught and logged.
296
+
297
+ ### Tests
298
+
299
+ Run the focused unit tests with Node.js 22.14:
300
+
301
+ ```bash
302
+ nvm use 22.14
303
+ yarn workspace @webex/internal-plugin-metrics test:unit --targets network-telemetry.ts
304
+ ```
305
+
32
306
  ## Maintainers
33
307
 
34
308
  This package is maintained by [Cisco Webex for Developers](https://developer.webex.com/).
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+
3
+ var _Object$defineProperty = require("@babel/runtime-corejs2/core-js/object/define-property");
4
+ _Object$defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.isAutomatedUserAgent = exports.isAutomatedUser = void 0;
8
+ var _isbot = require("isbot");
9
+ var isAutomatedUserAgent = exports.isAutomatedUserAgent = function isAutomatedUserAgent(userAgent) {
10
+ return (0, _isbot.isBot)(userAgent);
11
+ };
12
+ var automatedUser;
13
+ var isAutomatedUser = exports.isAutomatedUser = function isAutomatedUser() {
14
+ if (automatedUser === undefined) {
15
+ automatedUser = typeof window !== 'undefined' && typeof navigator !== 'undefined' && (Boolean(navigator.webdriver) || isAutomatedUserAgent(navigator.userAgent));
16
+ }
17
+ return automatedUser;
18
+ };
19
+ //# sourceMappingURL=automated-user.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_isbot","require","isAutomatedUserAgent","exports","userAgent","isBot","automatedUser","isAutomatedUser","undefined","window","navigator","Boolean","webdriver"],"sources":["automated-user.ts"],"sourcesContent":["import {isBot} from 'isbot';\n\nexport const isAutomatedUserAgent = (userAgent?: string | null): boolean => isBot(userAgent);\n\nlet automatedUser: boolean | undefined;\n\nexport const isAutomatedUser = (): boolean => {\n if (automatedUser === undefined) {\n automatedUser =\n typeof window !== 'undefined' &&\n typeof navigator !== 'undefined' &&\n (Boolean(navigator.webdriver) || isAutomatedUserAgent(navigator.userAgent));\n }\n\n return automatedUser;\n};\n"],"mappings":";;;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAEO,IAAMC,oBAAoB,GAAAC,OAAA,CAAAD,oBAAA,GAAG,SAAvBA,oBAAoBA,CAAIE,SAAyB;EAAA,OAAc,IAAAC,YAAK,EAACD,SAAS,CAAC;AAAA;AAE5F,IAAIE,aAAkC;AAE/B,IAAMC,eAAe,GAAAJ,OAAA,CAAAI,eAAA,GAAG,SAAlBA,eAAeA,CAAA,EAAkB;EAC5C,IAAID,aAAa,KAAKE,SAAS,EAAE;IAC/BF,aAAa,GACX,OAAOG,MAAM,KAAK,WAAW,IAC7B,OAAOC,SAAS,KAAK,WAAW,KAC/BC,OAAO,CAACD,SAAS,CAACE,SAAS,CAAC,IAAIV,oBAAoB,CAACQ,SAAS,CAACN,SAAS,CAAC,CAAC;EAC/E;EAEA,OAAOE,aAAa;AACtB,CAAC","ignoreList":[]}
package/dist/batcher.js CHANGED
@@ -81,6 +81,9 @@ var MetricsBatcher = _webexCore.Batcher.extend({
81
81
  handleHttpError: function handleHttpError(reason) {
82
82
  var _this2 = this;
83
83
  if (reason instanceof _webexCore.WebexHttpError.NetworkOrCORSError) {
84
+ if (!this.config.batcherRetryOnNetworkError) {
85
+ return (0, _apply.default)(_webexCore.Batcher.prototype.handleHttpError, this, [reason]);
86
+ }
84
87
  this.logger.warn('metrics-batcher: received network error submitting metrics, reenqueuing payload');
85
88
  return _promise.default.all(reason.options.body.metrics.map(function (item) {
86
89
  return new _promise.default(function (resolve) {
@@ -1 +1 @@
1
- {"version":3,"names":["_webexCore","require","_commonTimers","sym","_symbol","default","MetricsBatcher","Batcher","extend","namespace","prepareItem","item","env","process","NODE_ENV","appType","config","time","_now","version","webex","_promise","resolve","prepareRequest","queue","map","postTime","submitHttpRequest","payload","request","method","service","resource","body","metrics","waitForServiceTimeout","handleHttpSuccess","res","_this","all","options","acceptItem","handleHttpError","reason","_this2","WebexHttpError","NetworkOrCORSError","logger","warn","delay","nextDelay","batcherRetryPlateau","safeSetTimeout","rerequest","_apply","prototype","_this3","getDeferredForRequest","then","_ref","_ref2","_slicedToArray2","defer","req","enqueue","bounce","catch","reject","fingerprintRequest","fingerprintResponse","_default","exports"],"sources":["batcher.js"],"sourcesContent":["/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\nimport {Batcher, WebexHttpError} from '@webex/webex-core';\nimport {safeSetTimeout} from '@webex/common-timers';\n\nconst sym = Symbol('metric id');\n\n/**\n * @class\n * @extends Batcher\n * @memberof Metrics\n */\nconst MetricsBatcher = Batcher.extend({\n namespace: 'Metrics',\n\n /**\n * @param {any} item\n * @returns {Promise<any>}\n */\n prepareItem(item) {\n // Keep non-prod data out of metrics\n const env = process.env.NODE_ENV === 'production' ? null : 'TEST';\n\n item.appType = item.appType || this.config.appType;\n item.env = item.env || env;\n item.time = item.time || Date.now();\n item.version = item.version || this.webex.version;\n\n return Promise.resolve(item);\n },\n\n /**\n * @param {any[]} queue\n * @returns {Promise<any[]>}\n */\n prepareRequest(queue) {\n return Promise.resolve(\n queue.map((item) => {\n item.postTime = item.postTime || Date.now();\n\n return item;\n })\n );\n },\n\n /**\n * @param {any} payload\n * @returns {Promise<any>}\n */\n submitHttpRequest(payload) {\n return this.webex.request({\n method: 'POST',\n service: 'metrics',\n resource: 'metrics',\n body: {\n metrics: payload,\n },\n waitForServiceTimeout: this.webex.config.metrics.waitForServiceTimeout,\n });\n },\n\n /**\n * @param {any} res\n * @returns {Promise<any>}\n */\n handleHttpSuccess(res) {\n return Promise.all(res.options.body.metrics.map((item) => this.acceptItem(item)));\n },\n\n /**\n * @param {any} reason\n * @returns {Promise<any>}\n */\n handleHttpError(reason) {\n if (reason instanceof WebexHttpError.NetworkOrCORSError) {\n this.logger.warn(\n 'metrics-batcher: received network error submitting metrics, reenqueuing payload'\n );\n\n return Promise.all(\n reason.options.body.metrics.map(\n (item) =>\n new Promise((resolve) => {\n const delay = item[sym].nextDelay;\n\n if (delay < this.config.batcherRetryPlateau) {\n item[sym].nextDelay *= 2;\n }\n safeSetTimeout(() => {\n resolve(this.rerequest(item));\n }, delay);\n })\n )\n );\n }\n\n return Reflect.apply(Batcher.prototype.handleHttpError, this, [reason]);\n },\n\n /**\n * @param {any} item\n * @returns {Promise<any>}\n */\n rerequest(item) {\n return Promise.all([this.getDeferredForRequest(item), this.prepareItem(item)]).then(\n ([defer, req]) => {\n this.enqueue(req)\n .then(() => this.bounce())\n .catch((reason) => defer.reject(reason));\n }\n );\n },\n\n /**\n * @param {any} item\n * @returns {Promise<any>}\n */\n fingerprintRequest(item) {\n item[sym] = item[sym] || {\n nextDelay: 1000,\n };\n\n return Promise.resolve(item[sym]);\n },\n\n /**\n * @param {any} item\n * @returns {Promise<any>}\n */\n fingerprintResponse(item) {\n return Promise.resolve(item[sym]);\n },\n});\n\nexport default MetricsBatcher;\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_webexCore","require","_commonTimers","sym","_symbol","default","MetricsBatcher","Batcher","extend","namespace","prepareItem","item","env","process","NODE_ENV","appType","config","time","_now","version","webex","_promise","resolve","prepareRequest","queue","map","postTime","submitHttpRequest","payload","request","method","service","resource","body","metrics","waitForServiceTimeout","handleHttpSuccess","res","_this","all","options","acceptItem","handleHttpError","reason","_this2","WebexHttpError","NetworkOrCORSError","batcherRetryOnNetworkError","_apply","prototype","logger","warn","delay","nextDelay","batcherRetryPlateau","safeSetTimeout","rerequest","_this3","getDeferredForRequest","then","_ref","_ref2","_slicedToArray2","defer","req","enqueue","bounce","catch","reject","fingerprintRequest","fingerprintResponse","_default","exports"],"sources":["batcher.js"],"sourcesContent":["/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\nimport {Batcher, WebexHttpError} from '@webex/webex-core';\nimport {safeSetTimeout} from '@webex/common-timers';\n\nconst sym = Symbol('metric id');\n\n/**\n * @class\n * @extends Batcher\n * @memberof Metrics\n */\nconst MetricsBatcher = Batcher.extend({\n namespace: 'Metrics',\n\n /**\n * @param {any} item\n * @returns {Promise<any>}\n */\n prepareItem(item) {\n // Keep non-prod data out of metrics\n const env = process.env.NODE_ENV === 'production' ? null : 'TEST';\n\n item.appType = item.appType || this.config.appType;\n item.env = item.env || env;\n item.time = item.time || Date.now();\n item.version = item.version || this.webex.version;\n\n return Promise.resolve(item);\n },\n\n /**\n * @param {any[]} queue\n * @returns {Promise<any[]>}\n */\n prepareRequest(queue) {\n return Promise.resolve(\n queue.map((item) => {\n item.postTime = item.postTime || Date.now();\n\n return item;\n })\n );\n },\n\n /**\n * @param {any} payload\n * @returns {Promise<any>}\n */\n submitHttpRequest(payload) {\n return this.webex.request({\n method: 'POST',\n service: 'metrics',\n resource: 'metrics',\n body: {\n metrics: payload,\n },\n waitForServiceTimeout: this.webex.config.metrics.waitForServiceTimeout,\n });\n },\n\n /**\n * @param {any} res\n * @returns {Promise<any>}\n */\n handleHttpSuccess(res) {\n return Promise.all(res.options.body.metrics.map((item) => this.acceptItem(item)));\n },\n\n /**\n * @param {any} reason\n * @returns {Promise<any>}\n */\n handleHttpError(reason) {\n if (reason instanceof WebexHttpError.NetworkOrCORSError) {\n if (!this.config.batcherRetryOnNetworkError) {\n return Reflect.apply(Batcher.prototype.handleHttpError, this, [reason]);\n }\n\n this.logger.warn(\n 'metrics-batcher: received network error submitting metrics, reenqueuing payload'\n );\n\n return Promise.all(\n reason.options.body.metrics.map(\n (item) =>\n new Promise((resolve) => {\n const delay = item[sym].nextDelay;\n\n if (delay < this.config.batcherRetryPlateau) {\n item[sym].nextDelay *= 2;\n }\n safeSetTimeout(() => {\n resolve(this.rerequest(item));\n }, delay);\n })\n )\n );\n }\n\n return Reflect.apply(Batcher.prototype.handleHttpError, this, [reason]);\n },\n\n /**\n * @param {any} item\n * @returns {Promise<any>}\n */\n rerequest(item) {\n return Promise.all([this.getDeferredForRequest(item), this.prepareItem(item)]).then(\n ([defer, req]) => {\n this.enqueue(req)\n .then(() => this.bounce())\n .catch((reason) => defer.reject(reason));\n }\n );\n },\n\n /**\n * @param {any} item\n * @returns {Promise<any>}\n */\n fingerprintRequest(item) {\n item[sym] = item[sym] || {\n nextDelay: 1000,\n };\n\n return Promise.resolve(item[sym]);\n },\n\n /**\n * @param {any} item\n * @returns {Promise<any>}\n */\n fingerprintResponse(item) {\n return Promise.resolve(item[sym]);\n },\n});\n\nexport default MetricsBatcher;\n"],"mappings":";;;;;;;;;;;;;AAIA,IAAAA,UAAA,GAAAC,OAAA;AACA,IAAAC,aAAA,GAAAD,OAAA;AALA;AACA;AACA;;AAKA,IAAME,GAAG,GAAG,IAAAC,OAAA,CAAAC,OAAA,EAAO,WAAW,CAAC;;AAE/B;AACA;AACA;AACA;AACA;AACA,IAAMC,cAAc,GAAGC,kBAAO,CAACC,MAAM,CAAC;EACpCC,SAAS,EAAE,SAAS;EAEpB;AACF;AACA;AACA;EACEC,WAAW,WAAXA,WAAWA,CAACC,IAAI,EAAE;IAChB;IACA,IAAMC,GAAG,GAAGC,OAAO,CAACD,GAAG,CAACE,QAAQ,KAAK,YAAY,GAAG,IAAI,GAAG,MAAM;IAEjEH,IAAI,CAACI,OAAO,GAAGJ,IAAI,CAACI,OAAO,IAAI,IAAI,CAACC,MAAM,CAACD,OAAO;IAClDJ,IAAI,CAACC,GAAG,GAAGD,IAAI,CAACC,GAAG,IAAIA,GAAG;IAC1BD,IAAI,CAACM,IAAI,GAAGN,IAAI,CAACM,IAAI,IAAI,IAAAC,IAAA,CAAAb,OAAA,EAAS,CAAC;IACnCM,IAAI,CAACQ,OAAO,GAAGR,IAAI,CAACQ,OAAO,IAAI,IAAI,CAACC,KAAK,CAACD,OAAO;IAEjD,OAAOE,QAAA,CAAAhB,OAAA,CAAQiB,OAAO,CAACX,IAAI,CAAC;EAC9B,CAAC;EAED;AACF;AACA;AACA;EACEY,cAAc,WAAdA,cAAcA,CAACC,KAAK,EAAE;IACpB,OAAOH,QAAA,CAAAhB,OAAA,CAAQiB,OAAO,CACpBE,KAAK,CAACC,GAAG,CAAC,UAACd,IAAI,EAAK;MAClBA,IAAI,CAACe,QAAQ,GAAGf,IAAI,CAACe,QAAQ,IAAI,IAAAR,IAAA,CAAAb,OAAA,EAAS,CAAC;MAE3C,OAAOM,IAAI;IACb,CAAC,CACH,CAAC;EACH,CAAC;EAED;AACF;AACA;AACA;EACEgB,iBAAiB,WAAjBA,iBAAiBA,CAACC,OAAO,EAAE;IACzB,OAAO,IAAI,CAACR,KAAK,CAACS,OAAO,CAAC;MACxBC,MAAM,EAAE,MAAM;MACdC,OAAO,EAAE,SAAS;MAClBC,QAAQ,EAAE,SAAS;MACnBC,IAAI,EAAE;QACJC,OAAO,EAAEN;MACX,CAAC;MACDO,qBAAqB,EAAE,IAAI,CAACf,KAAK,CAACJ,MAAM,CAACkB,OAAO,CAACC;IACnD,CAAC,CAAC;EACJ,CAAC;EAED;AACF;AACA;AACA;EACEC,iBAAiB,WAAjBA,iBAAiBA,CAACC,GAAG,EAAE;IAAA,IAAAC,KAAA;IACrB,OAAOjB,QAAA,CAAAhB,OAAA,CAAQkC,GAAG,CAACF,GAAG,CAACG,OAAO,CAACP,IAAI,CAACC,OAAO,CAACT,GAAG,CAAC,UAACd,IAAI;MAAA,OAAK2B,KAAI,CAACG,UAAU,CAAC9B,IAAI,CAAC;IAAA,EAAC,CAAC;EACnF,CAAC;EAED;AACF;AACA;AACA;EACE+B,eAAe,WAAfA,eAAeA,CAACC,MAAM,EAAE;IAAA,IAAAC,MAAA;IACtB,IAAID,MAAM,YAAYE,yBAAc,CAACC,kBAAkB,EAAE;MACvD,IAAI,CAAC,IAAI,CAAC9B,MAAM,CAAC+B,0BAA0B,EAAE;QAC3C,OAAO,IAAAC,MAAA,CAAA3C,OAAA,EAAcE,kBAAO,CAAC0C,SAAS,CAACP,eAAe,EAAE,IAAI,EAAE,CAACC,MAAM,CAAC,CAAC;MACzE;MAEA,IAAI,CAACO,MAAM,CAACC,IAAI,CACd,iFACF,CAAC;MAED,OAAO9B,QAAA,CAAAhB,OAAA,CAAQkC,GAAG,CAChBI,MAAM,CAACH,OAAO,CAACP,IAAI,CAACC,OAAO,CAACT,GAAG,CAC7B,UAACd,IAAI;QAAA,OACH,IAAAU,QAAA,CAAAhB,OAAA,CAAY,UAACiB,OAAO,EAAK;UACvB,IAAM8B,KAAK,GAAGzC,IAAI,CAACR,GAAG,CAAC,CAACkD,SAAS;UAEjC,IAAID,KAAK,GAAGR,MAAI,CAAC5B,MAAM,CAACsC,mBAAmB,EAAE;YAC3C3C,IAAI,CAACR,GAAG,CAAC,CAACkD,SAAS,IAAI,CAAC;UAC1B;UACA,IAAAE,4BAAc,EAAC,YAAM;YACnBjC,OAAO,CAACsB,MAAI,CAACY,SAAS,CAAC7C,IAAI,CAAC,CAAC;UAC/B,CAAC,EAAEyC,KAAK,CAAC;QACX,CAAC,CAAC;MAAA,CACN,CACF,CAAC;IACH;IAEA,OAAO,IAAAJ,MAAA,CAAA3C,OAAA,EAAcE,kBAAO,CAAC0C,SAAS,CAACP,eAAe,EAAE,IAAI,EAAE,CAACC,MAAM,CAAC,CAAC;EACzE,CAAC;EAED;AACF;AACA;AACA;EACEa,SAAS,WAATA,SAASA,CAAC7C,IAAI,EAAE;IAAA,IAAA8C,MAAA;IACd,OAAOpC,QAAA,CAAAhB,OAAA,CAAQkC,GAAG,CAAC,CAAC,IAAI,CAACmB,qBAAqB,CAAC/C,IAAI,CAAC,EAAE,IAAI,CAACD,WAAW,CAACC,IAAI,CAAC,CAAC,CAAC,CAACgD,IAAI,CACjF,UAAAC,IAAA,EAAkB;MAAA,IAAAC,KAAA,OAAAC,eAAA,CAAAzD,OAAA,EAAAuD,IAAA;QAAhBG,KAAK,GAAAF,KAAA;QAAEG,GAAG,GAAAH,KAAA;MACVJ,MAAI,CAACQ,OAAO,CAACD,GAAG,CAAC,CACdL,IAAI,CAAC;QAAA,OAAMF,MAAI,CAACS,MAAM,CAAC,CAAC;MAAA,EAAC,CACzBC,KAAK,CAAC,UAACxB,MAAM;QAAA,OAAKoB,KAAK,CAACK,MAAM,CAACzB,MAAM,CAAC;MAAA,EAAC;IAC5C,CACF,CAAC;EACH,CAAC;EAED;AACF;AACA;AACA;EACE0B,kBAAkB,WAAlBA,kBAAkBA,CAAC1D,IAAI,EAAE;IACvBA,IAAI,CAACR,GAAG,CAAC,GAAGQ,IAAI,CAACR,GAAG,CAAC,IAAI;MACvBkD,SAAS,EAAE;IACb,CAAC;IAED,OAAOhC,QAAA,CAAAhB,OAAA,CAAQiB,OAAO,CAACX,IAAI,CAACR,GAAG,CAAC,CAAC;EACnC,CAAC;EAED;AACF;AACA;AACA;EACEmE,mBAAmB,WAAnBA,mBAAmBA,CAAC3D,IAAI,EAAE;IACxB,OAAOU,QAAA,CAAAhB,OAAA,CAAQiB,OAAO,CAACX,IAAI,CAACR,GAAG,CAAC,CAAC;EACnC;AACF,CAAC,CAAC;AAAC,IAAAoE,QAAA,GAAAC,OAAA,CAAAnE,OAAA,GAEYC,cAAc","ignoreList":[]}