@odigos/aws-cdk 0.0.20 → 0.0.22

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/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # Odigos CDK constructs for AWS
2
2
 
3
- Instrument AWS Lambda functions and ECS Fargate services with OpenTelemetry, from your own CDK app.
3
+ Instrument AWS Lambda functions, ECS Fargate services and Amazon Bedrock AgentCore Runtimes with
4
+ OpenTelemetry, from your own CDK app.
4
5
 
5
6
  ```bash
6
7
  npm install @odigos/aws-cdk@0.0.19
@@ -15,16 +16,17 @@ The Python distribution is built by jsii but is not published on PyPI;
15
16
  run `npm ci`, `npm run build`, then `npm run package` from `cdk/`, and install the wheel under `dist/python/`.
16
17
  For customer installation until PyPI publishing is enabled, use the CloudFormation instructions instead.
17
18
 
18
- | | Lambda | ECS Fargate |
19
- |---|---|---|
20
- | Construct | `OdigosLambdaInstrumentation` | `OdigosFargateInstrumentation` |
21
- | Mechanism | a layer, plus an exec wrapper or loader variable | agents staged into a shared task volume by a run-to-completion container |
22
- | Languages | python, nodejs, java, ruby | java, python, nodejs, dotnet, php, ruby |
23
- | Where telemetry goes | a collector in the same Lambda sandbox, which forwards | your destination, from the application process |
24
- | Language detection | from the function's declared runtime | none — you state the language |
19
+ | | Lambda | ECS Fargate | AgentCore Runtime |
20
+ |---|---|---|---|
21
+ | Construct | `OdigosLambdaInstrumentation` | `OdigosFargateInstrumentation` | `OdigosAgentCoreInstrumentation` |
22
+ | Mechanism | a layer, plus an exec wrapper or loader variable | agents staged into a shared task volume by a run-to-completion container | runtime environment variables; the SDK bundle is prepared into your artifact separately |
23
+ | Languages | python, nodejs, java, ruby | java, python, nodejs, dotnet, php, ruby | python (3.12), nodejs (22, CommonJS) |
24
+ | Where telemetry goes | a collector in the same Lambda sandbox, which forwards | your destination, from the application process | your OTLP/HTTP destination, from the application process |
25
+ | Language detection | from the function's declared runtime | none — you state the language | none — you state the language |
25
26
 
26
27
  Lambda writes `odigos:iac=v1` and exact SDK/collector layer ARNs as function tags. Fargate writes an
27
- `ODIGOS_IAC` environment marker on each application container. Neither claims connector-managed ownership.
28
+ `ODIGOS_IAC` environment marker on each application container, and AgentCore one on each runtime. None of
29
+ them claims connector-managed ownership.
28
30
 
29
31
  # AWS Lambda
30
32
 
@@ -458,6 +460,194 @@ automatic-mode source is owned by both: each `cdk deploy` reasserts your stack's
458
460
  reconcile reasserts the connector's, and every round trip registers a revision and rolls the service.
459
461
  Discovery-only (manual) mode is the combination that works.
460
462
 
463
+ # Amazon Bedrock AgentCore Runtime
464
+
465
+ ```ts
466
+ import {
467
+ OdigosAgentCoreInstrumentation,
468
+ OdigosAgentCoreLanguage,
469
+ OdigosAgentCoreDistribution,
470
+ OdigosAgentCoreDelivery, // only for ADOT-only artifacts, see below
471
+ } from '@odigos/aws-cdk';
472
+
473
+ const odigos = new OdigosAgentCoreInstrumentation(this, 'Odigos', {
474
+ destination: {
475
+ httpEndpoint: 'https://otlp.example.com:4318',
476
+ headers: { Authorization: 'Bearer <token>' },
477
+ },
478
+ });
479
+
480
+ odigos.instrument({
481
+ runtime: agentRuntime, // CfnRuntime, L2 Runtime, or CfnInclude resource
482
+ language: OdigosAgentCoreLanguage.PYTHON,
483
+ distribution: OdigosAgentCoreDistribution.ADOT, // the profile prepared into the artifact
484
+ });
485
+ ```
486
+
487
+ ```python
488
+ from odigos_aws_cdk import (
489
+ OdigosAgentCoreInstrumentation,
490
+ OdigosAgentCoreLanguage,
491
+ OdigosAgentCoreDistribution,
492
+ )
493
+
494
+ odigos = OdigosAgentCoreInstrumentation(self, "Odigos",
495
+ destination={
496
+ "http_endpoint": "https://otlp.example.com:4318",
497
+ "headers": {"Authorization": "Bearer <token>"},
498
+ },
499
+ )
500
+ odigos.instrument(
501
+ runtime=agent_runtime,
502
+ language=OdigosAgentCoreLanguage.PYTHON,
503
+ distribution=OdigosAgentCoreDistribution.ADOT,
504
+ )
505
+ ```
506
+
507
+ `runtime` is any `AWS::BedrockAgentCore::Runtime` resource: an L1 `CfnRuntime`, a raw `CfnResource`, a
508
+ resource from `CfnInclude.getResource()`, or a construct whose `node.defaultChild` is one (the L2
509
+ `Runtime` in newer `aws-cdk-lib` releases). The construct writes through property overrides on
510
+ `EnvironmentVariables`, so it needs no particular `aws-cdk-lib` version. Anything else throws at synth.
511
+
512
+ ## Prepare the artifact first
513
+
514
+ **This construct does not install anything.** The environment it writes switches on an Odigos SDK
515
+ bootstrap that must already be inside the artifact the runtime deploys; without it the variables are
516
+ inert, and Odigos reports the runtime as not conformant. Prepare the artifact in your build by adding the
517
+ Odigos package to the application's dependencies: `pip install "odigos-agentcore[adot]"` (or
518
+ `[openllmetry]`, matching `distribution`) or `npm install @odigos/agentcore`.
519
+
520
+ - **Container artifact:** Python needs nothing further; the package loads its dormant bootstrap at interpreter
521
+ start. For Node.js, append `--require <abs path>/node_modules/@odigos/agentcore/register.cjs` to
522
+ `NODE_OPTIONS`, keeping the application's existing flags.
523
+ - **Code (ZIP) artifact:** install the package into the directory you ZIP, and set the runtime's `EntryPoint`
524
+ to the wrapper followed by your original entry point: `["odigos_agentcore_start.py", "app.py"]` or
525
+ `["node_modules/@odigos/agentcore/odigos_agentcore_start.js", "index.js"]`. The wrapper starts the
526
+ bootstrap and then your application.
527
+
528
+ Without registry access, copy the bundle from `registry.odigos.io/odigos-agentcore-agents:<version>` instead
529
+ (`/var/odigos/agentcore/python/3.12` or `/var/odigos/agentcore/nodejs/22`, into the image at
530
+ `/opt/odigos/agentcore` or into the ZIP as `odigos-agentcore/`), and load its bootstrap before application
531
+ imports: append `/opt/odigos/agentcore/bootstrap/python` to `PYTHONPATH` or `--require
532
+ /opt/odigos/agentcore/bootstrap/node/register.cjs` to `NODE_OPTIONS`; in a ZIP, use the wrapper inside the
533
+ bundle, `odigos-agentcore/bootstrap/python/odigos_agentcore_start.py` or `.../node/odigos_agentcore_start.js`.
534
+
535
+ The full steps are at <https://docs.odigos.io/cloud-connectors/aws/workloads/agentcore/prepare>.
536
+ `AGENTCORE_AGENTS_IMAGE` exports the bundle image this package release pairs with.
537
+
538
+ ### ADOT only: `delivery: ADOPT`
539
+
540
+ An artifact that carries AWS Distro for OpenTelemetry and no Odigos package can be instrumented too.
541
+ Set `delivery: OdigosAgentCoreDelivery.ADOPT` (the default is `PACKAGE`), with the ADOT distribution:
542
+
543
+ ```ts
544
+ odigos.instrument({
545
+ runtime: agentRuntime,
546
+ language: OdigosAgentCoreLanguage.PYTHON,
547
+ delivery: OdigosAgentCoreDelivery.ADOPT, // the artifact carries ADOT only
548
+ });
549
+ ```
550
+
551
+ Prepare the artifact with ADOT and its own launcher:
552
+
553
+ - **Python:** add `aws-opentelemetry-distro` to the dependencies and start through `opentelemetry-instrument`:
554
+ a ZIP's `EntryPoint` becomes `["opentelemetry-instrument", "app.py"]`, a container's `CMD` is prefixed with
555
+ `opentelemetry-instrument`.
556
+ - **Node.js (CommonJS):** add `@aws/aws-distro-opentelemetry-node-autoinstrumentation` and append
557
+ `--require @aws/aws-distro-opentelemetry-node-autoinstrumentation/register` to `NODE_OPTIONS`, on the runtime
558
+ or in the image, keeping existing flags. The construct does not write `NODE_OPTIONS`.
559
+
560
+ The construct then writes the connector's adopt recipe (`agentCoreAdoptEnv`): the table below without
561
+ `ODIGOS_AGENTCORE_ENABLED` and `ODIGOS_AGENTCORE_DISTRO` (both removed), `OTEL_PROPAGATORS` set to
562
+ `tracecontext,baggage`, and `ODIGOS_AGENTCORE_PACKAGE` declaring the mode, for example
563
+ `{"v":1,"language":"python","distros":["python-agentcore-adot"],"mode":"adopt"}` (Node.js adds
564
+ `"moduleFormat":"commonjs"` before `mode`). The connector reads that mode and checks the runtime against the
565
+ adopt recipe. ADOT cannot root an invocation at the agent, so AgentCore's own service span stays missing from
566
+ the trace; the Odigos package adds it. Any distribution other than `ADOT` with `ADOPT` throws at synth.
567
+
568
+ `language` and `distribution` must describe what you prepared. They are written into
569
+ `ODIGOS_AGENTCORE_PACKAGE` and `ODIGOS_AGENTCORE_DISTRO`, which the connector checks against the
570
+ profile, and the bootstrap starts the profile the distro names. `distribution` defaults to `ADOT`.
571
+
572
+ | | `ADOT` (default) | `OPENLLMETRY` |
573
+ |---|---|---|
574
+ | Distro written | `<language>-agentcore-adot` | `<language>-agentcore-openllmetry` |
575
+ | SDK | AWS Distro for OpenTelemetry | OpenLLMetry Bedrock on the upstream SDK |
576
+
577
+ Only Python 3.12 and CommonJS Node.js 22 artifacts are qualified. Native ESM Node.js needs explicit SDK
578
+ initialization and is not covered by this recipe.
579
+
580
+ ## What it writes
581
+
582
+ With `delivery: PACKAGE` (the default; see above for `ADOPT`). Every key is compared exactly by the connector's observer, which rebuilds the same map from the
583
+ destination configured in Odigos:
584
+
585
+ | Variable | Value |
586
+ |---|---|
587
+ | `ODIGOS_AGENTCORE_ENABLED` | `true` |
588
+ | `ODIGOS_AGENTCORE_DISTRO` | `<language>-agentcore-<distribution>` |
589
+ | `ODIGOS_AGENTCORE_PACKAGE` | `{"v":1,"language":"<language>","distros":["<distro>"]}`, plus `"moduleFormat":"commonjs"` for Node.js |
590
+ | `ODIGOS_IAC` | `{"distro":"<distro>","recipe":"1","v":1}` |
591
+ | `DISABLE_ADOT_OBSERVABILITY` | `true` |
592
+ | `AGENT_OBSERVABILITY_ENABLED` | `false` |
593
+ | `OTEL_SERVICE_NAME` | see below |
594
+ | `OTEL_EXPORTER_OTLP_ENDPOINT` | `httpEndpoint` with trailing `/` removed |
595
+ | `OTEL_EXPORTER_OTLP_PROTOCOL` | `http/protobuf` |
596
+ | `OTEL_EXPORTER_OTLP_{TRACES,METRICS,LOGS}_ENDPOINT` | `<endpoint>/v1/traces`, `/v1/metrics`, `/v1/logs` |
597
+ | `OTEL_EXPORTER_OTLP_{TRACES,METRICS,LOGS}_PROTOCOL` | `http/protobuf` |
598
+ | `OTEL_{TRACES,METRICS,LOGS}_EXPORTER` | `otlp` when the signal is enabled, `none` otherwise |
599
+ | `OTEL_EXPORTER_OTLP_HEADERS` | the destination headers, URL-encoded and sorted; removed when there are none |
600
+ | `OTEL_SDK_DISABLED` | `false` |
601
+ | `OTEL_PROPAGATORS` | `tracecontext,baggage,xray` |
602
+ | `OTEL_TRACES_SAMPLER` | `parentbased_always_on` |
603
+ | `OTEL_AWS_APPLICATION_SIGNALS_ENABLED` | `false` |
604
+ | `OTEL_AWS_DYNAMIC_INSTRUMENTATION_ENABLED` | `false` |
605
+ | `OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT` | `false` |
606
+ | `TRACELOOP_TRACE_CONTENT` | `false` |
607
+ | `OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED` | `true` (also on Node.js, where it is inert) |
608
+ | `OTEL_PYTHON_DISTRO` (Python) | `aws_distro` (ADOT) or `distro` (OpenLLMetry) |
609
+ | `OTEL_PYTHON_CONFIGURATOR` (Python) | `aws_configurator` (ADOT) or `configurator` (OpenLLMetry) |
610
+ | `OTEL_PYTHON_DISABLED_INSTRUMENTATIONS` (Python) | `boto3` (ADOT) or `botocore,aws_langchain,aws_openai_agents,aws_llama-index,aws_crewai,aws_mcp` (OpenLLMetry) |
611
+
612
+ It also **removes** `OTEL_EXPORTER_OTLP_{TRACES,METRICS,LOGS}_HEADERS`, because a signal-specific header
613
+ overrides the shared credential, and `ODIGOS_MANAGED`, which is the connector's own ownership marker.
614
+ Other variables the runtime sets are kept. Replacing one the runtime already sets to a different value is
615
+ a synth warning. AgentCore allows at most 50 variables; the recipe uses 27–30 of them. Synth warns when
616
+ the known total would exceed 50, or when its size exceeds the platform byte limit (1536 bytes for V2 code
617
+ artifacts, 2560 for V2 containers).
618
+
619
+ Prompt, response and tool content capture stays off. The Python bootstrap also strips GenAI content
620
+ attributes that some instrumentations record regardless of that setting.
621
+
622
+ ## Destination
623
+
624
+ AgentCore exports **directly** to a global OTLP/HTTP destination. `httpEndpoint` is required and
625
+ `endpoint` (gRPC) is rejected. The URL must be an `http` or `https` base URL without credentials, query or
626
+ fragment, and without a per-signal `/v1/traces`, `/v1/metrics` or `/v1/logs` path: the recipe adds those
627
+ paths itself. `destination.headers` is written into `OTEL_EXPORTER_OTLP_HEADERS` as plain runtime
628
+ configuration, readable by anyone with `bedrock-agentcore:GetAgentRuntime`. Pass raw header values and
629
+ let the construct encode them.
630
+
631
+ ## Service names
632
+
633
+ `OTEL_SERVICE_NAME` defaults to the runtime's `AgentRuntimeName` when the template gives it as a literal
634
+ string. That is also the workload name Odigos uses, unless a service name override is configured there.
635
+ When the name is a token, such as a `Fn::Join` with the stack name, pass `serviceName`; synth throws
636
+ otherwise.
637
+
638
+ ## Signals
639
+
640
+ Same defaults as Lambda and Fargate: traces on, metrics and logs opt-in. They must match the signals the
641
+ destination has in Odigos. All three exporter selectors are written explicitly, and at least one signal
642
+ must be enabled.
643
+
644
+ ## Do not also enable automatic mode for these runtimes
645
+
646
+ The connector refuses to install or manage a runtime that carries `ODIGOS_IAC`, and reports it as an
647
+ error. Leave AgentCore sources in discovery-only (manual) mode in Odigos: Odigos observes and reports, and
648
+ your stack owns the configuration. To hand a runtime to automatic mode, remove this construct and deploy
649
+ first.
650
+
461
651
  # Bill of materials and removal
462
652
 
463
653
  | Flow | Resources and configuration left by deployment |
@@ -466,6 +656,7 @@ Discovery-only (manual) mode is the combination that works.
466
656
  | Lambda `IN_ACCOUNT` | The above plus one SAR nested stack/layer per artifact family and architecture; ADOT adds the shared collector application |
467
657
  | Application Signals | The above plus a managed-policy attachment on the Lambda role; account-wide discovery is configured separately |
468
658
  | Fargate | A task-definition revision with one non-essential copier, one shared volume, mounts/dependencies, activation/export environment and per-container IaC marker; an ECS deployment when the service references that revision |
659
+ | AgentCore Runtime | Environment variables on the runtime (export settings, profile selection, `ODIGOS_AGENTCORE_PACKAGE`, `ODIGOS_IAC`) and a new runtime version when it deploys. The prepared SDK bundle in your artifact comes from your own build, not this construct |
469
660
 
470
661
  The constructs do not create a regional Collector, network routes, telemetry destination, or customer
471
662
  credentials. Provision and remove those using their separate guides. Registry access and destination
@@ -477,7 +668,9 @@ To uninstall instrumentation while keeping the application:
477
668
  `instrument()` calls or aspect from your app. Restore any explicit loader override you no longer want.
478
669
  2. Run `cdk diff`, review removal of the instrumentation resources/settings, then run `cdk deploy`.
479
670
  For Lambda, publish the uninstrumented version and move every serving alias to it. For Fargate,
480
- ensure the service references the new task revision and wait for the rollout to finish.
671
+ ensure the service references the new task revision and wait for the rollout to finish. For
672
+ AgentCore, wait for the `DEFAULT` endpoint to serve the new version, update custom endpoints, and
673
+ remove the SDK bundle from your artifact build if you no longer want it.
481
674
  3. Verify the application is healthy and sends no new Odigos telemetry. Old published Lambda versions
482
675
  and ECS revisions remain instrumented until retired; review all traffic and rollback references first.
483
676
  4. SAR layers use retention policies and can remain after stack removal. After no function or published
@@ -499,7 +692,12 @@ To uninstall instrumentation while keeping the application:
499
692
  | `OdigosFargateInstrumentation` | the Fargate construct; `instrument(target)`, `instrumentAll(targets)` |
500
693
  | `OdigosFargateTarget` | one container to instrument: `container`, `language`, `service` / `serviceName`, `runtimeVersion`, `existingLoaderValue` |
501
694
  | `OdigosFargateLanguage` | `JAVA` \| `PYTHON` \| `NODEJS` \| `DOTNET` \| `PHP` \| `RUBY` |
502
- | `OdigosDestination` | where telemetry goes; exactly one endpoint on Lambda, either or both on Fargate |
695
+ | `OdigosAgentCoreInstrumentation` | the AgentCore construct; `instrument(target)` |
696
+ | `OdigosAgentCoreTarget` | one runtime to instrument: `runtime`, `language`, `distribution`, `delivery`, `serviceName` |
697
+ | `OdigosAgentCoreLanguage` | `PYTHON` \| `NODEJS` |
698
+ | `OdigosAgentCoreDistribution` | `ADOT` \| `OPENLLMETRY` |
699
+ | `OdigosAgentCoreDelivery` | `PACKAGE` (Odigos package or carrier bundle) \| `ADOPT` (ADOT only) |
700
+ | `OdigosDestination` | where telemetry goes; exactly one endpoint on Lambda, either or both on Fargate, `httpEndpoint` only on AgentCore |
503
701
  | `OdigosLayerSource` | `ODIGOS_PUBLIC` \| `IN_ACCOUNT` |
504
702
  | `OdigosInstrumentationMode` | `HANDLER` \| `WEB_SERVER` |
505
703
  | `OdigosJavaHandlerDistro` | the four Java wrappers |
@@ -507,6 +705,8 @@ To uninstall instrumentation while keeping the application:
507
705
  | `sidecarCommand`, `evaluateAppendPattern` | the Fargate staging command and loader-value rendering |
508
706
  | `LAYER_ARNS`, `ODIGOS_VERSION` | the baked layer table and the release it came from |
509
707
  | `FARGATE_AGENTS_IMAGE`, `FARGATE_DISTROS_VERSION` | the agents image this build stages, and the distros release its recipes mirror |
708
+ | `AGENTCORE_AGENTS_IMAGE`, `AGENTCORE_RECIPE_VERSION`, `AGENTCORE_DISTRIBUTIONS` | the AgentCore SDK bundle image for this release, the connector recipe version, and the profile catalog |
709
+ | `agentCoreEnvironment`, `renderAgentCoreHeaders` | the AgentCore environment recipe and header encoding (TypeScript only) |
510
710
 
511
711
  ## License
512
712
 
@@ -0,0 +1,84 @@
1
+ import { OdigosDestination } from './types';
2
+ /** `ODIGOS_AGENTCORE_PACKAGE` — the artifact preparation contract (`agentcore.PackageEnv`). */
3
+ export declare const AGENTCORE_PACKAGE_ENV = "ODIGOS_AGENTCORE_PACKAGE";
4
+ /** `ODIGOS_AGENTCORE_ENABLED` — switches the dormant bootstrap on (`agentcore.EnabledEnv`). */
5
+ export declare const AGENTCORE_ENABLED_ENV = "ODIGOS_AGENTCORE_ENABLED";
6
+ /** `ODIGOS_AGENTCORE_DISTRO` — which bundled profile the bootstrap starts (`agentcore.DistroEnv`). */
7
+ export declare const AGENTCORE_DISTRO_ENV = "ODIGOS_AGENTCORE_DISTRO";
8
+ /** The customer-owned instrumentation marker. */
9
+ export declare const AGENTCORE_IAC_ENV = "ODIGOS_IAC";
10
+ /** The connector's own ownership marker, which an IaC-managed runtime must never carry. */
11
+ export declare const AGENTCORE_MANAGED_ENV = "ODIGOS_MANAGED";
12
+ /** AgentCore's cap on environment variables per runtime. */
13
+ export declare const AGENTCORE_MAX_ENV_VARS = 50;
14
+ /** The environment one runtime is given: keys to set, and keys that must be absent. */
15
+ export interface AgentCoreEnvironment {
16
+ readonly set: {
17
+ [key: string]: string;
18
+ };
19
+ readonly remove: string[];
20
+ }
21
+ /**
22
+ * The connector catalog name for a language/profile pair, e.g. `python-agentcore-adot`.
23
+ *
24
+ * @throws if the pair is not in the catalog this package was generated from.
25
+ */
26
+ export declare function agentCoreDistroName(language: string, distribution: string): string;
27
+ /**
28
+ * Go's `url.QueryEscape` followed by `strings.ReplaceAll(s, "+", "%20")`, byte for byte.
29
+ *
30
+ * QueryEscape leaves only `A-Z a-z 0-9 - _ . ~` alone and percent-encodes every other UTF-8 byte in upper
31
+ * case, spelling a space `+`; the connector then turns that `+` into `%20` (a literal `+` was already
32
+ * `%2B`). `encodeURIComponent` differs on `! ' ( ) *`, so it is not a substitute.
33
+ */
34
+ export declare function agentCoreQueryEscape(value: string): string;
35
+ /**
36
+ * `OTEL_EXPORTER_OTLP_HEADERS` as the connector renders it: each pair encoded, then the `k=v` strings
37
+ * sorted (by the encoded text, as Go's `sort.Strings` does) and comma-joined. Empty for no headers.
38
+ *
39
+ * A key or value that is an unresolved token is passed through unencoded — encoding the token's
40
+ * placeholder text would destroy it — and the caller is expected to warn.
41
+ */
42
+ export declare function renderAgentCoreHeaders(headers?: {
43
+ [key: string]: string;
44
+ }): string;
45
+ /**
46
+ * Mirrors `agentCoreTarget`: AgentCore exports straight to a global OTLP/HTTP base URL.
47
+ *
48
+ * @throws on a gRPC endpoint, a URL with credentials, query or fragment, a per-signal `/v1/...` path, or
49
+ * no enabled signal.
50
+ */
51
+ export declare function validateAgentCoreDestination(dest: OdigosDestination): void;
52
+ /**
53
+ * The compact `ODIGOS_AGENTCORE_PACKAGE` value. Key order is `agentcore.Package`'s field order, which is
54
+ * what Go's `json.Marshal` of the struct emits; `moduleFormat` only for Node.js, where it is `commonjs`,
55
+ * and `mode` only for the adopt route (`agentCorePackageValue` / `agentCoreAdoptPackageValue`).
56
+ */
57
+ export declare function agentCorePackage(language: string, distro: string, mode?: string): string;
58
+ /**
59
+ * The compact `ODIGOS_IAC` value. Go marshals the connector's marker from a map, so its keys come out
60
+ * sorted: `distro`, `recipe`, `v`.
61
+ */
62
+ export declare function agentCoreIaCMarker(distro: string): string;
63
+ /**
64
+ * Mirrors `agentCoreEnv`, plus the two values the manual recipe adds: the preparation contract and the
65
+ * IaC marker. The connector's "" (remove) entries come back in `remove`, never as empty strings — an
66
+ * empty `OTEL_EXPORTER_OTLP_HEADERS` set in AWS is not the same as an absent one.
67
+ */
68
+ export declare function agentCoreEnvironment(language: string, distro: string, service: string, dest: OdigosDestination): AgentCoreEnvironment;
69
+ /**
70
+ * Mirrors `agentCoreAdoptEnv`, plus the adopt route's preparation contract and the IaC marker: the
71
+ * artifact runs ADOT only, so the bootstrap switches are removed and the X-Ray propagator is dropped
72
+ * (with an uninstrumented caller AgentCore sends only X-Amzn-Trace-Id, so the agent's server span becomes
73
+ * a root instead of a child of AgentCore's span). Only the ADOT distribution can be adopted.
74
+ */
75
+ export declare function agentCoreAdoptEnvironment(language: string, service: string, dest: OdigosDestination): AgentCoreEnvironment;
76
+ /**
77
+ * Mirrors `validateAgentCoreEnv` on the variables this recipe sets: at most 50, keys at most 100 bytes and
78
+ * values at most 5000.
79
+ *
80
+ * @throws when the recipe alone breaks a service limit.
81
+ */
82
+ export declare function validateAgentCoreEnvironment(env: {
83
+ [key: string]: string;
84
+ }): void;
@@ -0,0 +1,243 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AGENTCORE_MAX_ENV_VARS = exports.AGENTCORE_MANAGED_ENV = exports.AGENTCORE_IAC_ENV = exports.AGENTCORE_DISTRO_ENV = exports.AGENTCORE_ENABLED_ENV = exports.AGENTCORE_PACKAGE_ENV = void 0;
4
+ exports.agentCoreDistroName = agentCoreDistroName;
5
+ exports.agentCoreQueryEscape = agentCoreQueryEscape;
6
+ exports.renderAgentCoreHeaders = renderAgentCoreHeaders;
7
+ exports.validateAgentCoreDestination = validateAgentCoreDestination;
8
+ exports.agentCorePackage = agentCorePackage;
9
+ exports.agentCoreIaCMarker = agentCoreIaCMarker;
10
+ exports.agentCoreEnvironment = agentCoreEnvironment;
11
+ exports.agentCoreAdoptEnvironment = agentCoreAdoptEnvironment;
12
+ exports.validateAgentCoreEnvironment = validateAgentCoreEnvironment;
13
+ /**
14
+ * The Amazon Bedrock AgentCore Runtime environment recipe.
15
+ *
16
+ * A line-for-line mirror of the connector's `agentCoreEnv`, `agentCoreAdoptEnv`, `agentCoreTarget` and
17
+ * `validateAgentCoreEnv` (connectors/providers/aws/pkg/workload/instrumentor/agentcore_recipes.go) and its
18
+ * `ODIGOS_IAC` / `ODIGOS_AGENTCORE_PACKAGE` encodings (plan_agentcore.go, agentcore/runtime.go). The connector's observer
19
+ * rebuilds this exact map and diffs it key by key against the runtime's environment, so every value here
20
+ * is compared byte for byte: a re-ordered header list or a JSON marker with its keys in another order is
21
+ * reported as a non-conformant runtime, not tolerated as an equivalent spelling.
22
+ *
23
+ * Internal: exported from the package index for TypeScript callers only, like the Fargate recipes. jsii
24
+ * does not carry free functions into Python.
25
+ */
26
+ const aws_cdk_lib_1 = require("aws-cdk-lib");
27
+ const collector_config_1 = require("./collector-config");
28
+ const agentcore_1 = require("./generated/agentcore");
29
+ /** `ODIGOS_AGENTCORE_PACKAGE` — the artifact preparation contract (`agentcore.PackageEnv`). */
30
+ exports.AGENTCORE_PACKAGE_ENV = 'ODIGOS_AGENTCORE_PACKAGE';
31
+ /** `ODIGOS_AGENTCORE_ENABLED` — switches the dormant bootstrap on (`agentcore.EnabledEnv`). */
32
+ exports.AGENTCORE_ENABLED_ENV = 'ODIGOS_AGENTCORE_ENABLED';
33
+ /** `ODIGOS_AGENTCORE_DISTRO` — which bundled profile the bootstrap starts (`agentcore.DistroEnv`). */
34
+ exports.AGENTCORE_DISTRO_ENV = 'ODIGOS_AGENTCORE_DISTRO';
35
+ /** The customer-owned instrumentation marker. */
36
+ exports.AGENTCORE_IAC_ENV = 'ODIGOS_IAC';
37
+ /** The connector's own ownership marker, which an IaC-managed runtime must never carry. */
38
+ exports.AGENTCORE_MANAGED_ENV = 'ODIGOS_MANAGED';
39
+ /** AgentCore's cap on environment variables per runtime. */
40
+ exports.AGENTCORE_MAX_ENV_VARS = 50;
41
+ const OTLP_HTTP_PROTOCOL = 'http/protobuf';
42
+ const SIGNALS = ['TRACES', 'METRICS', 'LOGS'];
43
+ /**
44
+ * The connector catalog name for a language/profile pair, e.g. `python-agentcore-adot`.
45
+ *
46
+ * @throws if the pair is not in the catalog this package was generated from.
47
+ */
48
+ function agentCoreDistroName(language, distribution) {
49
+ const name = `${language}-agentcore-${distribution}`;
50
+ if (!agentcore_1.AGENTCORE_DISTRIBUTIONS.some((d) => d.name === name && d.language === language)) {
51
+ throw new Error(`Odigos: AgentCore distribution "${name}" is not in this package's catalog (${agentcore_1.AGENTCORE_DISTRIBUTIONS.map((d) => d.name).join(', ')}).`);
52
+ }
53
+ return name;
54
+ }
55
+ /**
56
+ * Go's `url.QueryEscape` followed by `strings.ReplaceAll(s, "+", "%20")`, byte for byte.
57
+ *
58
+ * QueryEscape leaves only `A-Z a-z 0-9 - _ . ~` alone and percent-encodes every other UTF-8 byte in upper
59
+ * case, spelling a space `+`; the connector then turns that `+` into `%20` (a literal `+` was already
60
+ * `%2B`). `encodeURIComponent` differs on `! ' ( ) *`, so it is not a substitute.
61
+ */
62
+ function agentCoreQueryEscape(value) {
63
+ let out = '';
64
+ for (const byte of Buffer.from(value, 'utf8')) {
65
+ const c = String.fromCharCode(byte);
66
+ if (/[A-Za-z0-9\-_.~]/.test(c)) {
67
+ out += c;
68
+ }
69
+ else if (byte === 0x20) {
70
+ out += '%20';
71
+ }
72
+ else {
73
+ out += '%' + byte.toString(16).toUpperCase().padStart(2, '0');
74
+ }
75
+ }
76
+ return out;
77
+ }
78
+ /**
79
+ * `OTEL_EXPORTER_OTLP_HEADERS` as the connector renders it: each pair encoded, then the `k=v` strings
80
+ * sorted (by the encoded text, as Go's `sort.Strings` does) and comma-joined. Empty for no headers.
81
+ *
82
+ * A key or value that is an unresolved token is passed through unencoded — encoding the token's
83
+ * placeholder text would destroy it — and the caller is expected to warn.
84
+ */
85
+ function renderAgentCoreHeaders(headers) {
86
+ const encode = (s) => (aws_cdk_lib_1.Token.isUnresolved(s) ? s : agentCoreQueryEscape(s));
87
+ return Object.entries(headers ?? {})
88
+ .map(([k, v]) => `${encode(k)}=${encode(v)}`)
89
+ .sort()
90
+ .join(',');
91
+ }
92
+ /**
93
+ * Mirrors `agentCoreTarget`: AgentCore exports straight to a global OTLP/HTTP base URL.
94
+ *
95
+ * @throws on a gRPC endpoint, a URL with credentials, query or fragment, a per-signal `/v1/...` path, or
96
+ * no enabled signal.
97
+ */
98
+ function validateAgentCoreDestination(dest) {
99
+ if (!dest.httpEndpoint || dest.endpoint) {
100
+ throw new Error('Odigos: AgentCore requires a destination with `httpEndpoint` (OTLP/HTTP) only. The runtime exports ' +
101
+ 'directly to it; a gRPC `endpoint` and managed collector routing are not supported.');
102
+ }
103
+ if (!aws_cdk_lib_1.Token.isUnresolved(dest.httpEndpoint)) {
104
+ let url;
105
+ try {
106
+ url = new URL(dest.httpEndpoint);
107
+ }
108
+ catch {
109
+ url = undefined;
110
+ }
111
+ if (!url || !url.host || !['http:', 'https:'].includes(url.protocol) || url.username || url.password || url.search || url.hash) {
112
+ throw new Error('Odigos: AgentCore requires an HTTP(S) OTLP base URL without credentials, query or fragment.');
113
+ }
114
+ const path = url.pathname.replace(/\/+$/, '');
115
+ if (['/v1/traces', '/v1/logs', '/v1/metrics'].some((suffix) => path.endsWith(suffix))) {
116
+ throw new Error('Odigos: AgentCore OTLP endpoint must be a base URL, without a per-signal /v1 path. The recipe ' +
117
+ 'appends /v1/traces, /v1/metrics and /v1/logs itself.');
118
+ }
119
+ }
120
+ (0, collector_config_1.validateDestination)(dest);
121
+ const enabled = (0, collector_config_1.resolvedSignals)(dest);
122
+ if (!enabled.traces && !enabled.metrics && !enabled.logs) {
123
+ throw new Error('Odigos: AgentCore cannot export the selected signals — the destination enables none of traces, ' +
124
+ 'metrics or logs. Note that metrics and logs are OFF by default.');
125
+ }
126
+ }
127
+ /**
128
+ * The compact `ODIGOS_AGENTCORE_PACKAGE` value. Key order is `agentcore.Package`'s field order, which is
129
+ * what Go's `json.Marshal` of the struct emits; `moduleFormat` only for Node.js, where it is `commonjs`,
130
+ * and `mode` only for the adopt route (`agentCorePackageValue` / `agentCoreAdoptPackageValue`).
131
+ */
132
+ function agentCorePackage(language, distro, mode) {
133
+ const value = { v: 1, language, distros: [distro] };
134
+ if (language === 'nodejs') {
135
+ value.moduleFormat = 'commonjs';
136
+ }
137
+ if (mode) {
138
+ value.mode = mode;
139
+ }
140
+ return JSON.stringify(value);
141
+ }
142
+ /**
143
+ * The compact `ODIGOS_IAC` value. Go marshals the connector's marker from a map, so its keys come out
144
+ * sorted: `distro`, `recipe`, `v`.
145
+ */
146
+ function agentCoreIaCMarker(distro) {
147
+ return JSON.stringify({ distro, recipe: agentcore_1.AGENTCORE_RECIPE_VERSION, v: 1 });
148
+ }
149
+ /**
150
+ * Mirrors `agentCoreEnv`, plus the two values the manual recipe adds: the preparation contract and the
151
+ * IaC marker. The connector's "" (remove) entries come back in `remove`, never as empty strings — an
152
+ * empty `OTEL_EXPORTER_OTLP_HEADERS` set in AWS is not the same as an absent one.
153
+ */
154
+ function agentCoreEnvironment(language, distro, service, dest) {
155
+ const ep = aws_cdk_lib_1.Token.isUnresolved(dest.httpEndpoint) ? dest.httpEndpoint : dest.httpEndpoint.replace(/\/+$/, '');
156
+ const enabled = (0, collector_config_1.resolvedSignals)(dest);
157
+ const set = {
158
+ [exports.AGENTCORE_ENABLED_ENV]: 'true',
159
+ [exports.AGENTCORE_DISTRO_ENV]: distro,
160
+ DISABLE_ADOT_OBSERVABILITY: 'true',
161
+ AGENT_OBSERVABILITY_ENABLED: 'false',
162
+ OTEL_SERVICE_NAME: service,
163
+ OTEL_EXPORTER_OTLP_ENDPOINT: ep,
164
+ OTEL_EXPORTER_OTLP_PROTOCOL: OTLP_HTTP_PROTOCOL,
165
+ OTEL_SDK_DISABLED: 'false',
166
+ OTEL_PROPAGATORS: 'tracecontext,baggage,xray',
167
+ OTEL_TRACES_SAMPLER: 'parentbased_always_on',
168
+ OTEL_AWS_APPLICATION_SIGNALS_ENABLED: 'false',
169
+ OTEL_AWS_DYNAMIC_INSTRUMENTATION_ENABLED: 'false',
170
+ OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT: 'false',
171
+ TRACELOOP_TRACE_CONTENT: 'false',
172
+ // Unconditional in the connector, including for Node.js, where it is inert.
173
+ OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED: 'true',
174
+ };
175
+ const remove = [];
176
+ const signalEnabled = { TRACES: enabled.traces, METRICS: enabled.metrics, LOGS: enabled.logs };
177
+ for (const signal of SIGNALS) {
178
+ set[`OTEL_${signal}_EXPORTER`] = signalEnabled[signal] ? 'otlp' : 'none';
179
+ set[`OTEL_EXPORTER_OTLP_${signal}_ENDPOINT`] = `${ep}/v1/${signal.toLowerCase()}`;
180
+ set[`OTEL_EXPORTER_OTLP_${signal}_PROTOCOL`] = OTLP_HTTP_PROTOCOL;
181
+ // Removed, not emptied: a signal-specific header would override the shared credential.
182
+ remove.push(`OTEL_EXPORTER_OTLP_${signal}_HEADERS`);
183
+ }
184
+ const headers = renderAgentCoreHeaders(dest.headers);
185
+ if (headers) {
186
+ set.OTEL_EXPORTER_OTLP_HEADERS = headers;
187
+ }
188
+ else {
189
+ remove.push('OTEL_EXPORTER_OTLP_HEADERS');
190
+ }
191
+ if (language === 'python') {
192
+ if (distro.endsWith('-adot')) {
193
+ set.OTEL_PYTHON_DISTRO = 'aws_distro';
194
+ set.OTEL_PYTHON_CONFIGURATOR = 'aws_configurator';
195
+ set.OTEL_PYTHON_DISABLED_INSTRUMENTATIONS = 'boto3';
196
+ }
197
+ else {
198
+ set.OTEL_PYTHON_DISTRO = 'distro';
199
+ set.OTEL_PYTHON_CONFIGURATOR = 'configurator';
200
+ set.OTEL_PYTHON_DISABLED_INSTRUMENTATIONS = 'botocore,aws_langchain,aws_openai_agents,aws_llama-index,aws_crewai,aws_mcp';
201
+ }
202
+ }
203
+ set[exports.AGENTCORE_PACKAGE_ENV] = agentCorePackage(language, distro);
204
+ set[exports.AGENTCORE_IAC_ENV] = agentCoreIaCMarker(distro);
205
+ remove.push(exports.AGENTCORE_MANAGED_ENV);
206
+ return { set, remove };
207
+ }
208
+ /**
209
+ * Mirrors `agentCoreAdoptEnv`, plus the adopt route's preparation contract and the IaC marker: the
210
+ * artifact runs ADOT only, so the bootstrap switches are removed and the X-Ray propagator is dropped
211
+ * (with an uninstrumented caller AgentCore sends only X-Amzn-Trace-Id, so the agent's server span becomes
212
+ * a root instead of a child of AgentCore's span). Only the ADOT distribution can be adopted.
213
+ */
214
+ function agentCoreAdoptEnvironment(language, service, dest) {
215
+ const distro = agentCoreDistroName(language, 'adot');
216
+ const env = agentCoreEnvironment(language, distro, service, dest);
217
+ const set = { ...env.set };
218
+ delete set[exports.AGENTCORE_ENABLED_ENV];
219
+ delete set[exports.AGENTCORE_DISTRO_ENV];
220
+ set.OTEL_PROPAGATORS = 'tracecontext,baggage';
221
+ set[exports.AGENTCORE_PACKAGE_ENV] = agentCorePackage(language, distro, 'adopt');
222
+ return { set, remove: [exports.AGENTCORE_ENABLED_ENV, exports.AGENTCORE_DISTRO_ENV, ...env.remove] };
223
+ }
224
+ /**
225
+ * Mirrors `validateAgentCoreEnv` on the variables this recipe sets: at most 50, keys at most 100 bytes and
226
+ * values at most 5000.
227
+ *
228
+ * @throws when the recipe alone breaks a service limit.
229
+ */
230
+ function validateAgentCoreEnvironment(env) {
231
+ if (Object.keys(env).length > exports.AGENTCORE_MAX_ENV_VARS) {
232
+ throw new Error(`Odigos: AgentCore environment would exceed the ${exports.AGENTCORE_MAX_ENV_VARS}-variable limit.`);
233
+ }
234
+ for (const [k, v] of Object.entries(env)) {
235
+ if (aws_cdk_lib_1.Token.isUnresolved(v)) {
236
+ continue;
237
+ }
238
+ if (Buffer.byteLength(k) > 100 || Buffer.byteLength(v) > 5000) {
239
+ throw new Error(`Odigos: AgentCore environment variable ${k} exceeds the service size limit (100-byte name, 5000-byte value).`);
240
+ }
241
+ }
242
+ }
243
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWdlbnRjb3JlLXJlY2lwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvYWdlbnRjb3JlLXJlY2lwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBNkNBLGtEQU1DO0FBU0Qsb0RBYUM7QUFTRCx3REFNQztBQVFELG9FQWlDQztBQU9ELDRDQVNDO0FBTUQsZ0RBRUM7QUFPRCxvREF3REM7QUFRRCw4REFhQztBQVFELG9FQVlDO0FBalFEOzs7Ozs7Ozs7Ozs7R0FZRztBQUNILDZDQUFvQztBQUNwQyx5REFBMEU7QUFDMUUscURBQTBGO0FBRzFGLCtGQUErRjtBQUNsRixRQUFBLHFCQUFxQixHQUFHLDBCQUEwQixDQUFDO0FBQ2hFLCtGQUErRjtBQUNsRixRQUFBLHFCQUFxQixHQUFHLDBCQUEwQixDQUFDO0FBQ2hFLHNHQUFzRztBQUN6RixRQUFBLG9CQUFvQixHQUFHLHlCQUF5QixDQUFDO0FBQzlELGlEQUFpRDtBQUNwQyxRQUFBLGlCQUFpQixHQUFHLFlBQVksQ0FBQztBQUM5QywyRkFBMkY7QUFDOUUsUUFBQSxxQkFBcUIsR0FBRyxnQkFBZ0IsQ0FBQztBQUN0RCw0REFBNEQ7QUFDL0MsUUFBQSxzQkFBc0IsR0FBRyxFQUFFLENBQUM7QUFFekMsTUFBTSxrQkFBa0IsR0FBRyxlQUFlLENBQUM7QUFDM0MsTUFBTSxPQUFPLEdBQXlDLENBQUMsUUFBUSxFQUFFLFNBQVMsRUFBRSxNQUFNLENBQUMsQ0FBQztBQVFwRjs7OztHQUlHO0FBQ0gsU0FBZ0IsbUJBQW1CLENBQUMsUUFBZ0IsRUFBRSxZQUFvQjtJQUN4RSxNQUFNLElBQUksR0FBRyxHQUFHLFFBQVEsY0FBYyxZQUFZLEVBQUUsQ0FBQztJQUNyRCxJQUFJLENBQUMsbUNBQXVCLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLElBQUksSUFBSSxDQUFDLENBQUMsUUFBUSxLQUFLLFFBQVEsQ0FBQyxFQUFF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Q0FBQyxFQUFFLENBQUM7QUFDdkYsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsU0FBZ0IsNEJBQTRCLENBQUMsR0FBOEI7SUFDekUsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sR0FBRyw4QkFBc0IsRUFBRSxDQUFDO1FBQ3JELE1BQU0sSUFBSSxLQUFLLENBQUMsa0RBQWtELDhCQUFzQixrQkFBa0IsQ0FBQyxDQUFDO0lBQzlHLENBQUM7SUFDRCxLQUFLLE1BQU0sQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQ3pDLElBQUksbUJBQUssQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUMxQixTQUFTO1FBQ1gsQ0FBQztRQUNELElBQUksTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsR0FBRyxHQUFHLElBQUksTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLEVBQUUsQ0FBQztZQUM5RCxNQUFNLElBQUksS0FBSyxDQUFDLDBDQUEwQyxDQUFDLG1FQUFtRSxDQUFDLENBQUM7UUFDbEksQ0FBQztJQUNILENBQUM7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBUaGUgQW1hem9uIEJlZHJvY2sgQWdlbnRDb3JlIFJ1bnRpbWUgZW52aXJvbm1lbnQgcmVjaXBlLlxuICpcbiAqIEEgbGluZS1mb3ItbGluZSBtaXJyb3Igb2YgdGhlIGNvbm5lY3RvcidzIGBhZ2VudENvcmVFbnZgLCBgYWdlbnRDb3JlQWRvcHRFbnZgLCBgYWdlbnRDb3JlVGFyZ2V0YCBhbmRcbiAqIGB2YWxpZGF0ZUFnZW50Q29yZUVudmAgKGNvbm5lY3RvcnMvcHJvdmlkZXJzL2F3cy9wa2cvd29ya2xvYWQvaW5zdHJ1bWVudG9yL2FnZW50Y29yZV9yZWNpcGVzLmdvKSBhbmQgaXRzXG4gKiBgT0RJR09TX0lBQ2AgLyBgT0RJR09TX0FHRU5UQ09SRV9QQUNLQUdFYCBlbmNvZGluZ3MgKHBsYW5fYWdlbnRjb3JlLmdvLCBhZ2VudGNvcmUvcnVudGltZS5nbykuIFRoZSBjb25uZWN0b3IncyBvYnNlcnZlclxuICogcmVidWlsZHMgdGhpcyBleGFjdCBtYXAgYW5kIGRpZmZzIGl0IGtleSBieSBrZXkgYWdhaW5zdCB0aGUgcnVudGltZSdzIGVudmlyb25tZW50LCBzbyBldmVyeSB2YWx1ZSBoZXJlXG4gKiBpcyBjb21wYXJlZCBieXRlIGZvciBieXRlOiBhIHJlLW9yZGVyZWQgaGVhZGVyIGxpc3Qgb3IgYSBKU09OIG1hcmtlciB3aXRoIGl0cyBrZXlzIGluIGFub3RoZXIgb3JkZXIgaXNcbiAqIHJlcG9ydGVkIGFzIGEgbm9uLWNvbmZvcm1hbnQgcnVudGltZSwgbm90IHRvbGVyYXRlZCBhcyBhbiBlcXVpdmFsZW50IHNwZWxsaW5nLlxuICpcbiAqIEludGVybmFsOiBleHBvcnRlZCBmcm9tIHRoZSBwYWNrYWdlIGluZGV4IGZvciBUeXBlU2NyaXB0IGNhbGxlcnMgb25seSwgbGlrZSB0aGUgRmFyZ2F0ZSByZWNpcGVzLiBqc2lpXG4gKiBkb2VzIG5vdCBjYXJyeSBmcmVlIGZ1bmN0aW9ucyBpbnRvIFB5dGhvbi5cbiAqL1xuaW1wb3J0IHsgVG9rZW4gfSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgeyByZXNvbHZlZFNpZ25hbHMsIHZhbGlkYXRlRGVzdGluYXRpb24gfSBmcm9tICcuL2NvbGxlY3Rvci1jb25maWcnO1xuaW1wb3J0IHsgQUdFTlRDT1JFX0RJU1RSSUJVVElPTlMsIEFHRU5UQ09SRV9SRUNJUEVfVkVSU0lPTiB9IGZyb20gJy4vZ2VuZXJhdGVkL2FnZW50Y29yZSc7XG5pbXBvcnQgeyBPZGlnb3NEZXN0aW5hdGlvbiB9IGZyb20gJy4vdHlwZXMnO1xuXG4vKiogYE9ESUdPU19BR0VOVENPUkVfUEFDS0FHRWAg4oCUIHRoZSBhcnRpZmFjdCBwcmVwYXJhdGlvbiBjb250cmFjdCAoYGFnZW50Y29yZS5QYWNrYWdlRW52YCkuICovXG5leHBvcnQgY29uc3QgQUdFTlRDT1JFX1BBQ0tBR0VfRU5WID0gJ09ESUdPU19BR0VOVENPUkVfUEFDS0FHRSc7XG4vKiogYE9ESUdPU19BR0VOVENPUkVfRU5BQkxFRGAg4oCUIHN3aXRjaGVzIHRoZSBkb3JtYW50IGJvb3RzdHJhcCBvbiAoYGFnZW50Y29yZS5FbmFibGVkRW52YCkuICovXG5leHBvcnQgY29uc3QgQUdFTlRDT1JFX0VOQUJMRURfRU5WID0gJ09ESUdPU19BR0VOVENPUkVfRU5BQkxFRCc7XG4vKiogYE9ESUdPU19BR0VOVENPUkVfRElTVFJPYCDigJQgd2hpY2ggYnVuZGxlZCBwcm9maWxlIHRoZSBib290c3RyYXAgc3RhcnRzIChgYWdlbnRjb3JlLkRpc3Ryb0VudmApLiAqL1xuZXhwb3J0IGNvbnN0IEFHRU5UQ09SRV9ESVNUUk9fRU5WID0gJ09ESUdPU19BR0VOVENPUkVfRElTVFJPJztcbi8qKiBUaGUgY3VzdG9tZXItb3duZWQgaW5zdHJ1bWVudGF0aW9uIG1hcmtlci4gKi9cbmV4cG9ydCBjb25zdCBBR0VOVENPUkVfSUFDX0VOViA9ICdPRElHT1NfSUFDJztcbi8qKiBUaGUgY29ubmVjdG9yJ3Mgb3duIG93bmVyc2hpcCBtYXJrZXIsIHdoaWNoIGFuIElhQy1tYW5hZ2VkIHJ1bnRpbWUgbXVzdCBuZXZlciBjYXJyeS4gKi9cbmV4cG9ydCBjb25zdCBBR0VOVENPUkVfTUFOQUdFRF9FTlYgPSAnT0RJR09TX01BTkFHRUQnO1xuLyoqIEFnZW50Q29yZSdzIGNhcCBvbiBlbnZpcm9ubWVudCB2YXJpYWJsZXMgcGVyIHJ1bnRpbWUuICovXG5leHBvcnQgY29uc3QgQUdFTlRDT1JFX01BWF9FTlZfVkFSUyA9IDUwO1xuXG5jb25zdCBPVExQX0hUVFBfUFJPVE9DT0wgPSAnaHR0cC9wcm90b2J1Zic7XG5jb25zdCBTSUdOQUxTOiBBcnJheTwnVFJBQ0VTJyB8ICdNRVRSSUNTJyB8ICdMT0dTJz4gPSBbJ1RSQUNFUycsICdNRVRSSUNTJywgJ0xPR1MnXTtcblxuLyoqIFRoZSBlbnZpcm9ubWVudCBvbmUgcnVudGltZSBpcyBnaXZlbjoga2V5cyB0byBzZXQsIGFuZCBrZXlzIHRoYXQgbXVzdCBiZSBhYnNlbnQuICovXG5leHBvcnQgaW50ZXJmYWNlIEFnZW50Q29yZUVudmlyb25tZW50IHtcbiAgcmVhZG9ubHkgc2V0OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9O1xuICByZWFkb25seSByZW1vdmU6IHN0cmluZ1tdO1xufVxuXG4vKipcbiAqIFRoZSBjb25uZWN0b3IgY2F0YWxvZyBuYW1lIGZvciBhIGxhbmd1YWdlL3Byb2ZpbGUgcGFpciwgZS5nLiBgcHl0aG9uLWFnZW50Y29yZS1hZG90YC5cbiAqXG4gKiBAdGhyb3dzIGlmIHRoZSBwYWlyIGlzIG5vdCBpbiB0aGUgY2F0YWxvZyB0aGlzIHBhY2thZ2Ugd2FzIGdlbmVyYXRlZCBmcm9tLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYWdlbnRDb3JlRGlzdHJvTmFtZShsYW5ndWFnZTogc3RyaW5nLCBkaXN0cmlidXRpb246IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IG5hbWUgPSBgJHtsYW5ndWFnZX0tYWdlbnRjb3JlLSR7ZGlzdHJpYnV0aW9ufWA7XG4gIGlmICghQUdFTlRDT1JFX0RJU1RSSUJVVElPTlMuc29tZSgoZCkgPT4gZC5uYW1lID09PSBuYW1lICYmIGQubGFuZ3VhZ2UgPT09IGxhbmd1YWdlKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgT2RpZ29zOiBBZ2VudENvcmUgZGlzdHJpYnV0aW9uIFwiJHtuYW1lfVwiIGlzIG5vdCBpbiB0aGlzIHBhY2thZ2UncyBjYXRhbG9nICgke0FHRU5UQ09SRV9ESVNUUklCVVRJT05TLm1hcCgoZCkgPT4gZC5uYW1lKS5qb2luKCcsICcpfSkuYCk7XG4gIH1cbiAgcmV0dXJuIG5hbWU7XG59XG5cbi8qKlxuICogR28ncyBgdXJsLlF1ZXJ5RXNjYXBlYCBmb2xsb3dlZCBieSBgc3RyaW5ncy5SZXBsYWNlQWxsKHMsIFwiK1wiLCBcIiUyMFwiKWAsIGJ5dGUgZm9yIGJ5dGUuXG4gKlxuICogUXVlcnlFc2NhcGUgbGVhdmVzIG9ubHkgYEEtWiBhLXogMC05IC0gXyAuIH5gIGFsb25lIGFuZCBwZXJjZW50LWVuY29kZXMgZXZlcnkgb3RoZXIgVVRGLTggYnl0ZSBpbiB1cHBlclxuICogY2FzZSwgc3BlbGxpbmcgYSBzcGFjZSBgK2A7IHRoZSBjb25uZWN0b3IgdGhlbiB0dXJucyB0aGF0IGArYCBpbnRvIGAlMjBgIChhIGxpdGVyYWwgYCtgIHdhcyBhbHJlYWR5XG4gKiBgJTJCYCkuIGBlbmNvZGVVUklDb21wb25lbnRgIGRpZmZlcnMgb24gYCEgJyAoICkgKmAsIHNvIGl0IGlzIG5vdCBhIHN1YnN0aXR1dGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhZ2VudENvcmVRdWVyeUVzY2FwZSh2YWx1ZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgbGV0IG91dCA9ICcnO1xuICBmb3IgKGNvbnN0IGJ5dGUgb2YgQnVmZmVyLmZyb20odmFsdWUsICd1dGY4JykpIHtcbiAgICBjb25zdCBjID0gU3RyaW5nLmZyb21DaGFyQ29kZShieXRlKTtcbiAgICBpZiAoL1tBLVphLXowLTlcXC1fLn5dLy50ZXN0KGMpKSB7XG4gICAgICBvdXQgKz0gYztcbiAgICB9IGVsc2UgaWYgKGJ5dGUgPT09IDB4MjApIHtcbiAgICAgIG91dCArPSAnJTIwJztcbiAgICB9IGVsc2Uge1xuICAgICAgb3V0ICs9ICclJyArIGJ5dGUudG9TdHJpbmcoMTYpLnRvVXBwZXJDYXNlKCkucGFkU3RhcnQoMiwgJzAnKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG91dDtcbn1cblxuLyoqXG4gKiBgT1RFTF9FWFBPUlRFUl9PVExQX0hFQURFUlNgIGFzIHRoZSBjb25uZWN0b3IgcmVuZGVycyBpdDogZWFjaCBwYWlyIGVuY29kZWQsIHRoZW4gdGhlIGBrPXZgIHN0cmluZ3NcbiAqIHNvcnRlZCAoYnkgdGhlIGVuY29kZWQgdGV4dCwgYXMgR28ncyBgc29ydC5TdHJpbmdzYCBkb2VzKSBhbmQgY29tbWEtam9pbmVkLiBFbXB0eSBmb3Igbm8gaGVhZGVycy5cbiAqXG4gKiBBIGtleSBvciB2YWx1ZSB0aGF0IGlzIGFuIHVucmVzb2x2ZWQgdG9rZW4gaXMgcGFzc2VkIHRocm91Z2ggdW5lbmNvZGVkIOKAlCBlbmNvZGluZyB0aGUgdG9rZW4nc1xuICogcGxhY2Vob2xkZXIgdGV4dCB3b3VsZCBkZXN0cm95IGl0IOKAlCBhbmQgdGhlIGNhbGxlciBpcyBleHBlY3RlZCB0byB3YXJuLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVuZGVyQWdlbnRDb3JlSGVhZGVycyhoZWFkZXJzPzogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSk6IHN0cmluZyB7XG4gIGNvbnN0IGVuY29kZSA9IChzOiBzdHJpbmcpOiBzdHJpbmcgPT4gKFRva2VuLmlzVW5yZXNvbHZlZChzKSA/IHMgOiBhZ2VudENvcmVRdWVyeUVzY2FwZShzKSk7XG4gIHJldHVybiBPYmplY3QuZW50cmllcyhoZWFkZXJzID8/IHt9KVxuICAgIC5tYXAoKFtrLCB2XSkgPT4gYCR7ZW5jb2RlKGspfT0ke2VuY29kZSh2KX1gKVxuICAgIC5zb3J0KClcbiAgICAuam9pbignLCcpO1xufVxuXG4vKipcbiAqIE1pcnJvcnMgYGFnZW50Q29yZVRhcmdldGA6IEFnZW50Q29yZSBleHBvcnRzIHN0cmFpZ2h0IHRvIGEgZ2xvYmFsIE9UTFAvSFRUUCBiYXNlIFVSTC5cbiAqXG4gKiBAdGhyb3dzIG9uIGEgZ1JQQyBlbmRwb2ludCwgYSBVUkwgd2l0aCBjcmVkZW50aWFscywgcXVlcnkgb3IgZnJhZ21lbnQsIGEgcGVyLXNpZ25hbCBgL3YxLy4uLmAgcGF0aCwgb3JcbiAqIG5vIGVuYWJsZWQgc2lnbmFsLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVBZ2VudENvcmVEZXN0aW5hdGlvbihkZXN0OiBPZGlnb3NEZXN0aW5hdGlvbik6IHZvaWQge1xuICBpZiAoIWRlc3QuaHR0cEVuZHBvaW50IHx8IGRlc3QuZW5kcG9pbnQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAnT2RpZ29zOiBBZ2VudENvcmUgcmVxdWlyZXMgYSBkZXN0aW5hdGlvbiB3aXRoIGBodHRwRW5kcG9pbnRgIChPVExQL0hUVFApIG9ubHkuIFRoZSBydW50aW1lIGV4cG9ydHMgJyArXG4gICAgICAgICdkaXJlY3RseSB0byBpdDsgYSBnUlBDIGBlbmRwb2ludGAgYW5kIG1hbmFnZWQgY29sbGVjdG9yIHJvdXRpbmcgYXJlIG5vdCBzdXBwb3J0ZWQuJyxcbiAgICApO1xuICB9XG4gIGlmICghVG9rZW4uaXNVbnJlc29sdmVkKGRlc3QuaHR0cEVuZHBvaW50KSkge1xuICAgIGxldCB1cmw6IFVSTDtcbiAgICB0cnkge1xuICAgICAgdXJsID0gbmV3IFVSTChkZXN0Lmh0dHBFbmRwb2ludCk7XG4gICAgfSBjYXRjaCB7XG4gICAgICB1cmwgPSB1bmRlZmluZWQgYXMgdW5rbm93biBhcyBVUkw7XG4gICAgfVxuICAgIGlmICghdXJsIHx8ICF1cmwuaG9zdCB8fCAhWydodHRwOicsICdodHRwczonXS5pbmNsdWRlcyh1cmwucHJvdG9jb2wpIHx8IHVybC51c2VybmFtZSB8fCB1cmwucGFzc3dvcmQgfHwgdXJsLnNlYXJjaCB8fCB1cmwuaGFzaCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdPZGlnb3M6IEFnZW50Q29yZSByZXF1aXJlcyBhbiBIVFRQKFMpIE9UTFAgYmFzZSBVUkwgd2l0aG91dCBjcmVkZW50aWFscywgcXVlcnkgb3IgZnJhZ21lbnQuJyk7XG4gICAgfVxuICAgIGNvbnN0IHBhdGggPSB1cmwucGF0aG5hbWUucmVwbGFjZSgvXFwvKyQvLCAnJyk7XG4gICAgaWYgKFsnL3YxL3RyYWNlcycsICcvdjEvbG9ncycsICcvdjEvbWV0cmljcyddLnNvbWUoKHN1ZmZpeCkgPT4gcGF0aC5lbmRzV2l0aChzdWZmaXgpKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAnT2RpZ29zOiBBZ2VudENvcmUgT1RMUCBlbmRwb2ludCBtdXN0IGJlIGEgYmFzZSBVUkwsIHdpdGhvdXQgYSBwZXItc2lnbmFsIC92MSBwYXRoLiBUaGUgcmVjaXBlICcgK1xuICAgICAgICAgICdhcHBlbmRzIC92MS90cmFjZXMsIC92MS9tZXRyaWNzIGFuZCAvdjEvbG9ncyBpdHNlbGYuJyxcbiAgICAgICk7XG4gICAgfVxuICB9XG4gIHZhbGlkYXRlRGVzdGluYXRpb24oZGVzdCk7XG4gIGNvbnN0IGVuYWJsZWQgPSByZXNvbHZlZFNpZ25hbHMoZGVzdCk7XG4gIGlmICghZW5hYmxlZC50cmFjZXMgJiYgIWVuYWJsZWQubWV0cmljcyAmJiAhZW5hYmxlZC5sb2dzKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgJ09kaWdvczogQWdlbnRDb3JlIGNhbm5vdCBleHBvcnQgdGhlIHNlbGVjdGVkIHNpZ25hbHMg4oCUIHRoZSBkZXN0aW5hdGlvbiBlbmFibGVzIG5vbmUgb2YgdHJhY2VzLCAnICtcbiAgICAgICAgJ21ldHJpY3Mgb3IgbG9ncy4gTm90ZSB0aGF0IG1ldHJpY3MgYW5kIGxvZ3MgYXJlIE9GRiBieSBkZWZhdWx0LicsXG4gICAgKTtcbiAgfVxufVxuXG4vKipcbiAqIFRoZSBjb21wYWN0IGBPRElHT1NfQUdFTlRDT1JFX1BBQ0tBR0VgIHZhbHVlLiBLZXkgb3JkZXIgaXMgYGFnZW50Y29yZS5QYWNrYWdlYCdzIGZpZWxkIG9yZGVyLCB3aGljaCBpc1xuICogd2hhdCBHbydzIGBqc29uLk1hcnNoYWxgIG9mIHRoZSBzdHJ1Y3QgZW1pdHM7IGBtb2R1bGVGb3JtYXRgIG9ubHkgZm9yIE5vZGUuanMsIHdoZXJlIGl0IGlzIGBjb21tb25qc2AsXG4gKiBhbmQgYG1vZGVgIG9ubHkgZm9yIHRoZSBhZG9wdCByb3V0ZSAoYGFnZW50Q29yZVBhY2thZ2VWYWx1ZWAgLyBgYWdlbnRDb3JlQWRvcHRQYWNrYWdlVmFsdWVgKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFnZW50Q29yZVBhY2thZ2UobGFuZ3VhZ2U6IHN0cmluZywgZGlzdHJvOiBzdHJpbmcsIG1vZGU/OiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCB2YWx1ZTogeyBba2V5OiBzdHJpbmddOiB1bmtub3duIH0gPSB7IHY6IDEsIGxhbmd1YWdlLCBkaXN0cm9zOiBbZGlzdHJvXSB9O1xuICBpZiAobGFuZ3VhZ2UgPT09ICdub2RlanMnKSB7XG4gICAgdmFsdWUubW9kdWxlRm9ybWF0ID0gJ2NvbW1vbmpzJztcbiAgfVxuICBpZiAobW9kZSkge1xuICAgIHZhbHVlLm1vZGUgPSBtb2RlO1xuICB9XG4gIHJldHVybiBKU09OLnN0cmluZ2lmeSh2YWx1ZSk7XG59XG5cbi8qKlxuICogVGhlIGNvbXBhY3QgYE9ESUdPU19JQUNgIHZhbHVlLiBHbyBtYXJzaGFscyB0aGUgY29ubmVjdG9yJ3MgbWFya2VyIGZyb20gYSBtYXAsIHNvIGl0cyBrZXlzIGNvbWUgb3V0XG4gKiBzb3J0ZWQ6IGBkaXN0cm9gLCBgcmVjaXBlYCwgYHZgLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYWdlbnRDb3JlSWFDTWFya2VyKGRpc3Rybzogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHsgZGlzdHJvLCByZWNpcGU6IEFHRU5UQ09SRV9SRUNJUEVfVkVSU0lPTiwgdjogMSB9KTtcbn1cblxuLyoqXG4gKiBNaXJyb3JzIGBhZ2VudENvcmVFbnZgLCBwbHVzIHRoZSB0d28gdmFsdWVzIHRoZSBtYW51YWwgcmVjaXBlIGFkZHM6IHRoZSBwcmVwYXJhdGlvbiBjb250cmFjdCBhbmQgdGhlXG4gKiBJYUMgbWFya2VyLiBUaGUgY29ubmVjdG9yJ3MgXCJcIiAocmVtb3ZlKSBlbnRyaWVzIGNvbWUgYmFjayBpbiBgcmVtb3ZlYCwgbmV2ZXIgYXMgZW1wdHkgc3RyaW5ncyDigJQgYW5cbiAqIGVtcHR5IGBPVEVMX0VYUE9SVEVSX09UTFBfSEVBREVSU2Agc2V0IGluIEFXUyBpcyBub3QgdGhlIHNhbWUgYXMgYW4gYWJzZW50IG9uZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFnZW50Q29yZUVudmlyb25tZW50KFxuICBsYW5ndWFnZTogc3RyaW5nLFxuICBkaXN0cm86IHN0cmluZyxcbiAgc2VydmljZTogc3RyaW5nLFxuICBkZXN0OiBPZGlnb3NEZXN0aW5hdGlvbixcbik6IEFnZW50Q29yZUVudmlyb25tZW50IHtcbiAgY29uc3QgZXAgPSBUb2tlbi5pc1VucmVzb2x2ZWQoZGVzdC5odHRwRW5kcG9pbnQpID8gZGVzdC5odHRwRW5kcG9pbnQhIDogZGVzdC5odHRwRW5kcG9pbnQhLnJlcGxhY2UoL1xcLyskLywgJycpO1xuICBjb25zdCBlbmFibGVkID0gcmVzb2x2ZWRTaWduYWxzKGRlc3QpO1xuICBjb25zdCBzZXQ6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0gPSB7XG4gICAgW0FHRU5UQ09SRV9FTkFCTEVEX0VOVl06ICd0cnVlJyxcbiAgICBbQUdFTlRDT1JFX0RJU1RST19FTlZdOiBkaXN0cm8sXG4gICAgRElTQUJMRV9BRE9UX09CU0VSVkFCSUxJVFk6ICd0cnVlJyxcbiAgICBBR0VOVF9PQlNFUlZBQklMSVRZX0VOQUJMRUQ6ICdmYWxzZScsXG4gICAgT1RFTF9TRVJWSUNFX05BTUU6IHNlcnZpY2UsXG4gICAgT1RFTF9FWFBPUlRFUl9PVExQX0VORFBPSU5UOiBlcCxcbiAgICBPVEVMX0VYUE9SVEVSX09UTFBfUFJPVE9DT0w6IE9UTFBfSFRUUF9QUk9UT0NPTCxcbiAgICBPVEVMX1NES19ESVNBQkxFRDogJ2ZhbHNlJyxcbiAgICBPVEVMX1BST1BBR0FUT1JTOiAndHJhY2Vjb250ZXh0LGJhZ2dhZ2UseHJheScsXG4gICAgT1RFTF9UUkFDRVNfU0FNUExFUjogJ3BhcmVudGJhc2VkX2Fsd2F5c19vbicsXG4gICAgT1RFTF9BV1NfQVBQTElDQVRJT05fU0lHTkFMU19FTkFCTEVEOiAnZmFsc2UnLFxuICAgIE9URUxfQVdTX0RZTkFNSUNfSU5TVFJVTUVOVEFUSU9OX0VOQUJMRUQ6ICdmYWxzZScsXG4gICAgT1RFTF9JTlNUUlVNRU5UQVRJT05fR0VOQUlfQ0FQVFVSRV9NRVNTQUdFX0NPTlRFTlQ6ICdmYWxzZScsXG4gICAgVFJBQ0VMT09QX1RSQUNFX0NPTlRFTlQ6ICdmYWxzZScsXG4gICAgLy8gVW5jb25kaXRpb25hbCBpbiB0aGUgY29ubmVjdG9yLCBpbmNsdWRpbmcgZm9yIE5vZGUuanMsIHdoZXJlIGl0IGlzIGluZXJ0LlxuICAgIE9URUxfUFlUSE9OX0xPR0dJTkdfQVVUT19JTlNUUlVNRU5UQVRJT05fRU5BQkxFRDogJ3RydWUnLFxuICB9O1xuICBjb25zdCByZW1vdmU6IHN0cmluZ1tdID0gW107XG4gIGNvbnN0IHNpZ25hbEVuYWJsZWQgPSB7IFRSQUNFUzogZW5hYmxlZC50cmFjZXMsIE1FVFJJQ1M6IGVuYWJsZWQubWV0cmljcywgTE9HUzogZW5hYmxlZC5sb2dzIH07XG4gIGZvciAoY29uc3Qgc2lnbmFsIG9mIFNJR05BTFMpIHtcbiAgICBzZXRbYE9URUxfJHtzaWduYWx9X0VYUE9SVEVSYF0gPSBzaWduYWxFbmFibGVkW3NpZ25hbF0gPyAnb3RscCcgOiAnbm9uZSc7XG4gICAgc2V0W2BPVEVMX0VYUE9SVEVSX09UTFBfJHtzaWduYWx9X0VORFBPSU5UYF0gPSBgJHtlcH0vdjEvJHtzaWduYWwudG9Mb3dlckNhc2UoKX1gO1xuICAgIHNldFtgT1RFTF9FWFBPUlRFUl9PVExQXyR7c2lnbmFsfV9QUk9UT0NPTGBdID0gT1RMUF9IVFRQX1BST1RPQ09MO1xuICAgIC8vIFJlbW92ZWQsIG5vdCBlbXB0aWVkOiBhIHNpZ25hbC1zcGVjaWZpYyBoZWFkZXIgd291bGQgb3ZlcnJpZGUgdGhlIHNoYXJlZCBjcmVkZW50aWFsLlxuICAgIHJlbW92ZS5wdXNoKGBPVEVMX0VYUE9SVEVSX09UTFBfJHtzaWduYWx9X0hFQURFUlNgKTtcbiAgfVxuICBjb25zdCBoZWFkZXJzID0gcmVuZGVyQWdlbnRDb3JlSGVhZGVycyhkZXN0LmhlYWRlcnMpO1xuICBpZiAoaGVhZGVycykge1xuICAgIHNldC5PVEVMX0VYUE9SVEVSX09UTFBfSEVBREVSUyA9IGhlYWRlcnM7XG4gIH0gZWxzZSB7XG4gICAgcmVtb3ZlLnB1c2goJ09URUxfRVhQT1JURVJfT1RMUF9IRUFERVJTJyk7XG4gIH1cbiAgaWYgKGxhbmd1YWdlID09PSAncHl0aG9uJykge1xuICAgIGlmIChkaXN0cm8uZW5kc1dpdGgoJy1hZG90JykpIHtcbiAgICAgIHNldC5PVEVMX1BZVEhPTl9ESVNUUk8gPSAnYXdzX2Rpc3Rybyc7XG4gICAgICBzZXQuT1RFTF9QWVRIT05fQ09ORklHVVJBVE9SID0gJ2F3c19jb25maWd1cmF0b3InO1xuICAgICAgc2V0Lk9URUxfUFlUSE9OX0RJU0FCTEVEX0lOU1RSVU1FTlRBVElPTlMgPSAnYm90bzMnO1xuICAgIH0gZWxzZSB7XG4gICAgICBzZXQuT1RFTF9QWVRIT05fRElTVFJPID0gJ2Rpc3Rybyc7XG4gICAgICBzZXQuT1RFTF9QWVRIT05fQ09ORklHVVJBVE9SID0gJ2NvbmZpZ3VyYXRvcic7XG4gICAgICBzZXQuT1RFTF9QWVRIT05fRElTQUJMRURfSU5TVFJVTUVOVEFUSU9OUyA9ICdib3RvY29yZSxhd3NfbGFuZ2NoYWluLGF3c19vcGVuYWlfYWdlbnRzLGF3c19sbGFtYS1pbmRleCxhd3NfY3Jld2FpLGF3c19tY3AnO1xuICAgIH1cbiAgfVxuICBzZXRbQUdFTlRDT1JFX1BBQ0tBR0VfRU5WXSA9IGFnZW50Q29yZVBhY2thZ2UobGFuZ3VhZ2UsIGRpc3Rybyk7XG4gIHNldFtBR0VOVENPUkVfSUFDX0VOVl0gPSBhZ2VudENvcmVJYUNNYXJrZXIoZGlzdHJvKTtcbiAgcmVtb3ZlLnB1c2goQUdFTlRDT1JFX01BTkFHRURfRU5WKTtcbiAgcmV0dXJuIHsgc2V0LCByZW1vdmUgfTtcbn1cblxuLyoqXG4gKiBNaXJyb3JzIGBhZ2VudENvcmVBZG9wdEVudmAsIHBsdXMgdGhlIGFkb3B0IHJvdXRlJ3MgcHJlcGFyYXRpb24gY29udHJhY3QgYW5kIHRoZSBJYUMgbWFya2VyOiB0aGVcbiAqIGFydGlmYWN0IHJ1bnMgQURPVCBvbmx5LCBzbyB0aGUgYm9vdHN0cmFwIHN3aXRjaGVzIGFyZSByZW1vdmVkIGFuZCB0aGUgWC1SYXkgcHJvcGFnYXRvciBpcyBkcm9wcGVkXG4gKiAod2l0aCBhbiB1bmluc3RydW1lbnRlZCBjYWxsZXIgQWdlbnRDb3JlIHNlbmRzIG9ubHkgWC1BbXpuLVRyYWNlLUlkLCBzbyB0aGUgYWdlbnQncyBzZXJ2ZXIgc3BhbiBiZWNvbWVzXG4gKiBhIHJvb3QgaW5zdGVhZCBvZiBhIGNoaWxkIG9mIEFnZW50Q29yZSdzIHNwYW4pLiBPbmx5IHRoZSBBRE9UIGRpc3RyaWJ1dGlvbiBjYW4gYmUgYWRvcHRlZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFnZW50Q29yZUFkb3B0RW52aXJvbm1lbnQoXG4gIGxhbmd1YWdlOiBzdHJpbmcsXG4gIHNlcnZpY2U6IHN0cmluZyxcbiAgZGVzdDogT2RpZ29zRGVzdGluYXRpb24sXG4pOiBBZ2VudENvcmVFbnZpcm9ubWVudCB7XG4gIGNvbnN0IGRpc3RybyA9IGFnZW50Q29yZURpc3Ryb05hbWUobGFuZ3VhZ2UsICdhZG90Jyk7XG4gIGNvbnN0IGVudiA9IGFnZW50Q29yZUVudmlyb25tZW50KGxhbmd1YWdlLCBkaXN0cm8sIHNlcnZpY2UsIGRlc3QpO1xuICBjb25zdCBzZXQgPSB7IC4uLmVudi5zZXQgfTtcbiAgZGVsZXRlIHNldFtBR0VOVENPUkVfRU5BQkxFRF9FTlZdO1xuICBkZWxldGUgc2V0W0FHRU5UQ09SRV9ESVNUUk9fRU5WXTtcbiAgc2V0Lk9URUxfUFJPUEFHQVRPUlMgPSAndHJhY2Vjb250ZXh0LGJhZ2dhZ2UnO1xuICBzZXRbQUdFTlRDT1JFX1BBQ0tBR0VfRU5WXSA9IGFnZW50Q29yZVBhY2thZ2UobGFuZ3VhZ2UsIGRpc3RybywgJ2Fkb3B0Jyk7XG4gIHJldHVybiB7IHNldCwgcmVtb3ZlOiBbQUdFTlRDT1JFX0VOQUJMRURfRU5WLCBBR0VOVENPUkVfRElTVFJPX0VOViwgLi4uZW52LnJlbW92ZV0gfTtcbn1cblxuLyoqXG4gKiBNaXJyb3JzIGB2YWxpZGF0ZUFnZW50Q29yZUVudmAgb24gdGhlIHZhcmlhYmxlcyB0aGlzIHJlY2lwZSBzZXRzOiBhdCBtb3N0IDUwLCBrZXlzIGF0IG1vc3QgMTAwIGJ5dGVzIGFuZFxuICogdmFsdWVzIGF0IG1vc3QgNTAwMC5cbiAqXG4gKiBAdGhyb3dzIHdoZW4gdGhlIHJlY2lwZSBhbG9uZSBicmVha3MgYSBzZXJ2aWNlIGxpbWl0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVBZ2VudENvcmVFbnZpcm9ubWVudChlbnY6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0pOiB2b2lkIHtcbiAgaWYgKE9iamVjdC5rZXlzKGVudikubGVuZ3RoID4gQUdFTlRDT1JFX01BWF9FTlZfVkFSUykge1xuICAgIHRocm93IG5ldyBFcnJvcihgT2RpZ29zOiBBZ2VudENvcmUgZW52aXJvbm1lbnQgd291bGQgZXhjZWVkIHRoZSAke0FHRU5UQ09SRV9NQVhfRU5WX1ZBUlN9LXZhcmlhYmxlIGxpbWl0LmApO1xuICB9XG4gIGZvciAoY29uc3QgW2ssIHZdIG9mIE9iamVjdC5lbnRyaWVzKGVudikpIHtcbiAgICBpZiAoVG9rZW4uaXNVbnJlc29sdmVkKHYpKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgaWYgKEJ1ZmZlci5ieXRlTGVuZ3RoKGspID4gMTAwIHx8IEJ1ZmZlci5ieXRlTGVuZ3RoKHYpID4gNTAwMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBPZGlnb3M6IEFnZW50Q29yZSBlbnZpcm9ubWVudCB2YXJpYWJsZSAke2t9IGV4Y2VlZHMgdGhlIHNlcnZpY2Ugc2l6ZSBsaW1pdCAoMTAwLWJ5dGUgbmFtZSwgNTAwMC1ieXRlIHZhbHVlKS5gKTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==