{/* Shared partial: Agent Manager installation (Phase 2).
     Imported by on-k3d.mdx and on-your-environment.mdx.
     Props expected from parent:
       - props.version            — release version string (e.g. "0.12.0")
       - props.rewriteJwksForK3d  — (boolean, optional) if true, rewrites the JWKS URI
         so the gateway reaches the AMP API via the Docker host network (k3d only)
       - props.expandRegistryConfig — (boolean, optional) if true, shows registry config
         expanded instead of collapsed (for non-k3d environments)
*/}

export const GwOperatorConfig = ({version, rewriteJwksForK3d}) => {
  const baseUrl = `https://raw.githubusercontent.com/wso2/agent-manager/amp/v${version}/deployments/values/api-platform-operator-full-config.yaml`;
  if (rewriteJwksForK3d) {
    return (
      <>
        <p>Download the config, rewrite the JWKS URI for k3d (so the gateway can reach the AMP API via the Docker host network), then apply:</p>
        <pre><code className="language-bash">{`curl -fsSL ${baseUrl} \\
  | sed 's|http://amp-api.wso2-amp.svc.cluster.local:9000/auth/external/jwks.json|http://host.k3d.internal:9000/auth/external/jwks.json|g' \\
  | kubectl apply -f -`}</code></pre>
      </>
    );
  }
  return (
    <pre><code className="language-bash">{`kubectl apply -f ${baseUrl}`}</code></pre>
  );
};

The Agent Manager installs as a set of Helm charts on top of OpenChoreo. The components fall into two groups based on install order:

1. **Agent Manager Core :** Gateway Operator, Agent Manager and Platform Resources (agent component types, workflow templates etc). Each depends on the one before it.
2. **Extensions :** Secret Management, Observability, Evaluation extensions and the AI Gateway Extension.

:::info Prerequisites
Thunder (identity provider) must be installed before proceeding — see the Thunder installation step in Phase 1. The variables `THUNDER_PUBLIC_URL`, `THUNDER_INTERNAL_URL`, `CONSOLE_PUBLIC_URL`, `API_PUBLIC_URL`, `OBS_API_PUBLIC_URL`, and `INSTRUMENTATION_URL` must be set from the Configuration Variables section.
:::

---

### Core Components

Install these in order — each depends on the one before it.

#### Step 1: Gateway Operator

Manages API Gateway resources and enables secure, authenticated trace ingestion into the Observability Plane.

```bash
helm install gateway-operator \
  oci://ghcr.io/wso2/api-platform/helm-charts/gateway-operator \
  --version 0.5.0 \
  --namespace ${DATA_PLANE_NS} \
  --set logging.level=debug \
  --set gateway.helm.chartVersion=1.0.0 \
  --timeout 600s
```

Wait for the operator to be ready:

```bash
kubectl wait --for=condition=Available \
  deployment -l app.kubernetes.io/name=gateway-operator \
  -n ${DATA_PLANE_NS} --timeout=300s
```

Apply the Gateway Operator configuration (JWT/JWKS authentication and rate limiting):

<GwOperatorConfig version={props.version} rewriteJwksForK3d={props.rewriteJwksForK3d} />

Grant RBAC for WSO2 API Platform CRDs to the Data Plane cluster-agent:

```bash
kubectl apply -f - <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: wso2-api-platform-gateway-module
rules:
  - apiGroups: ["gateway.api-platform.wso2.com"]
    resources: ["restapis", "apigateways"]
    verbs: ["*"]
  - apiGroups: ["gateway.kgateway.dev"]
    resources: ["backends"]
    verbs: ["*"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: wso2-api-platform-gateway-module
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: wso2-api-platform-gateway-module
subjects:
  - kind: ServiceAccount
    name: cluster-agent-dataplane
    namespace: ${DATA_PLANE_NS}
EOF
```

Deploy the observability gateway and trace API:

```bash
kubectl apply -f https://raw.githubusercontent.com/wso2/agent-manager/amp/v${VERSION}/deployments/values/obs-gateway.yaml

kubectl wait --for=condition=Programmed \
  apigateway/obs-gateway -n ${DATA_PLANE_NS} --timeout=180s

kubectl apply -f https://raw.githubusercontent.com/wso2/agent-manager/amp/v${VERSION}/deployments/values/otel-collector-rest-api.yaml

kubectl wait --for=condition=Programmed \
  restapi/traces-api-secure -n ${DATA_PLANE_NS} --timeout=120s
```

:::tip Verify
```bash
kubectl get apigateway obs-gateway -n ${DATA_PLANE_NS}
# STATUS should show "Programmed"
```
:::

#### Step 2: Agent Manager (API + Console + PostgreSQL)

The core platform: a Go API server, a React web console, and a PostgreSQL database.

```bash
helm install amp \
  oci://${HELM_CHART_REGISTRY}/wso2-agent-manager \
  --version ${VERSION} \
  --namespace ${AMP_NS} \
  --create-namespace \
  --set console.config.instrumentationUrl="${INSTRUMENTATION_URL}" \
  --set console.config.auth.baseUrl="${THUNDER_PUBLIC_URL}" \
  --set console.config.auth.signInRedirectURL="${CONSOLE_PUBLIC_URL}/login" \
  --set console.config.auth.signOutRedirectURL="${CONSOLE_PUBLIC_URL}/login" \
  --set console.config.apiBaseUrl="${API_PUBLIC_URL}" \
  --set console.config.obsApiBaseUrl="${OBS_API_PUBLIC_URL}" \
  --set agentManagerService.config.keyManager.issuer="${THUNDER_PUBLIC_URL}" \
  --set agentManagerService.config.keyManager.jwksUrl="${THUNDER_INTERNAL_URL}/oauth2/jwks" \
  --set agentManagerService.config.oidc.tokenUrl="${THUNDER_INTERNAL_URL}/oauth2/token" \
  --set agentManagerService.config.openChoreo.baseURL="${OPENCHOREO_INTERNAL_URL}" \
  --timeout 1800s
```

Wait for all components:

```bash
# PostgreSQL
kubectl wait --for=jsonpath='{.status.readyReplicas}'=1 \
  statefulset/amp-postgresql -n ${AMP_NS} --timeout=600s

# API server
kubectl wait --for=condition=Available \
  deployment/amp-api -n ${AMP_NS} --timeout=600s

# Console
kubectl wait --for=condition=Available \
  deployment/amp-console -n ${AMP_NS} --timeout=600s
```

:::tip Verify
```bash
kubectl get pods -n ${AMP_NS}
# Expected: amp-postgresql-0 (Running), amp-api-xxx (Running), amp-console-xxx (Running)
```
:::

#### Step 3: Platform Resources

Creates the default Organization, Project, Environment, DeploymentPipeline, and workflow template resources that the console needs on first login. This chart also configures the **container registry endpoint** used by build workflows to push agent images.

```bash
helm install amp-platform-resources \
  oci://${HELM_CHART_REGISTRY}/wso2-amp-platform-resources-extension \
  --version ${VERSION} \
  --namespace ${DEFAULT_NS} \
  --timeout 1800s
```

export const RegistryConfig = ({expanded}) => {
  const content = (
    <>
      <p>The chart defaults are configured for a local k3d cluster with an in-cluster registry at <code>host.k3d.internal:10082</code>. For other environments, override the registry settings:</p>
      <pre><code className="language-bash">{`# Example: external registry with a base domain
helm install amp-platform-resources \\
  oci://\${HELM_CHART_REGISTRY}/wso2-amp-platform-resources-extension \\
  --version \${VERSION} \\
  --namespace \${DEFAULT_NS} \\
  --set global.baseDomain="yourdomain.com" \\
  --set global.defaultResources.registry.tlsVerify=true \\
  --timeout 1800s
# Registry endpoint will be: registry.yourdomain.com

# Example: explicit registry endpoint
helm install amp-platform-resources \\
  oci://\${HELM_CHART_REGISTRY}/wso2-amp-platform-resources-extension \\
  --version \${VERSION} \\
  --namespace \${DEFAULT_NS} \\
  --set global.registry.endpoint="your-registry.example.com:5000" \\
  --set global.defaultResources.registry.tlsVerify=true \\
  --timeout 1800s`}</code></pre>
      <table>
        <thead><tr><th>Value</th><th>Default</th><th>Description</th></tr></thead>
        <tbody>
          <tr><td><code>global.registry.endpoint</code></td><td><code>host.k3d.internal:10082</code></td><td>Registry endpoint for pushing images</td></tr>
          <tr><td><code>global.baseDomain</code></td><td><code>""</code></td><td>When set, registry endpoint becomes <code>registry.&lt;baseDomain&gt;</code></td></tr>
          <tr><td><code>global.defaultResources.registry.tlsVerify</code></td><td><code>false</code></td><td>Enable TLS verification for registry connections</td></tr>
        </tbody>
      </table>
    </>
  );
  if (expanded) {
    return (<><h5>Container registry configuration</h5>{content}</>);
  }
  return (<details><summary>Container registry configuration</summary>{content}</details>);
};

<RegistryConfig expanded={props.expandRegistryConfig} />

---

### Extensions

These can be installed in any order after Core is ready.

#### Step 4: Secrets Extension (OpenBao)

Provides runtime secret injection for deployed agents. Uses [OpenBao](https://openbao.org/) as the secrets backend.

```bash
helm install amp-secrets \
  oci://${HELM_CHART_REGISTRY}/wso2-amp-secrets-extension \
  --version ${VERSION} \
  --namespace ${SECRETS_NS} \
  --create-namespace \
  --set openbao.server.dev.enabled=true \
  --timeout 600s
```

```bash
kubectl wait --for=jsonpath='{.status.readyReplicas}'=1 \
  statefulset/amp-secrets-openbao -n ${SECRETS_NS} --timeout=300s
```

:::warning
Dev mode uses an in-memory backend — secrets are lost on restart. For production, disable dev mode and configure persistent storage.
:::

#### Step 5: Observability Extension (Traces Observer)

Deploys the Traces Observer service that queries and serves trace data to the console.

```bash
helm install amp-observability-traces \
  oci://${HELM_CHART_REGISTRY}/wso2-amp-observability-extension \
  --version ${VERSION} \
  --namespace ${OBSERVABILITY_NS} \
  --timeout 1800s

kubectl wait --for=condition=Available \
  deployment/amp-traces-observer -n ${OBSERVABILITY_NS} --timeout=600s
```

#### Step 6: Evaluation Extension

Installs workflow templates for running automated evaluations (accuracy, safety, reasoning, tool usage) against agent traces.

```bash
helm install amp-evaluation-extension \
  oci://${HELM_CHART_REGISTRY}/wso2-amp-evaluation-extension \
  --version ${VERSION} \
  --namespace ${BUILD_CI_NS} \
  --timeout 1800s
```

:::info
The default `publisher.apiKey` must match `publisherApiKey.value` in the Agent Manager chart. Both default to `amp-internal-api-key`.
:::

#### Step 7: AI Gateway Extension

Registers the AI Gateway with the Agent Manager and deploys the gateway stack. **Install this last** — it requires the Agent Manager API to be healthy and Thunder to be ready for token exchange.

The `gateway.vhost` is the URL that deployed agents use to reach the AI Gateway. It must be set to the in-cluster service URL so that agent workloads running inside the cluster can route LLM traffic through the gateway.

```bash
helm install amp-ai-gateway \
  oci://${HELM_CHART_REGISTRY}/wso2-amp-ai-gateway-extension \
  --version ${VERSION} \
  --namespace ${DATA_PLANE_NS} \
  --set apiGateway.controlPlane.host="amp-api-gateway-manager.${AMP_NS}.svc.cluster.local:9243" \
  --set agentManager.apiUrl="http://amp-api.${AMP_NS}.svc.cluster.local:9000/api/v1" \
  --set agentManager.idp.tokenUrl="${THUNDER_INTERNAL_URL}/oauth2/token" \
  --set gateway.vhost="http://default-ai-gateway-gateway-runtime.${DATA_PLANE_NS}.svc.cluster.local:8084" \
  --timeout 1800s

kubectl wait --for=condition=complete job/amp-gateway-bootstrap \
  -n ${DATA_PLANE_NS} --timeout=300s
```

:::tip Verify
```bash
kubectl get jobs -n ${DATA_PLANE_NS} | grep amp-gateway-bootstrap
# STATUS should show "Complete"
```
:::

<details>
<summary>Exposing the AI Gateway publicly</summary>

The AI Gateway's `LoadBalancer` service is already externally reachable if your cluster supports it. To use a public URL as the vhost instead of the in-cluster service URL:

```bash
# Get the AI Gateway's external IP
AI_GW_IP=$(kubectl get svc default-ai-gateway-gateway-runtime -n ${DATA_PLANE_NS} \
  -o jsonpath='{.status.loadBalancer.ingress[0].ip}')

# Use a nip.io domain or your own DNS record
export AI_GATEWAY_VHOST="http://ai-gateway.${AI_GW_IP//./-}.nip.io:8084"

# Set during install:
#   --set gateway.vhost="${AI_GATEWAY_VHOST}"
```

For production, point a DNS record (e.g., `ai-gateway.yourdomain.com`) at the LoadBalancer IP and configure TLS termination. Agents running outside the cluster will need this public URL to reach the gateway.

</details>
